team-goals / index.html
JayStormX8's picture
Add 3 files
116c004 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TeamPerf | Performance Dashboard</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#4F46E5',
secondary: '#10B981',
dark: '#1F2937',
light: '#F9FAFB'
}
}
}
}
</script>
<style>
.progress-ring__circle {
transition: stroke-dashoffset 0.5s;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
.chart-container {
position: relative;
height: 250px;
}
.fade-in {
animation: fadeIn 0.5s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.modal {
transition: opacity 0.3s ease;
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-white shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
<div class="flex items-center space-x-2">
<div class="w-8 h-8 rounded-md bg-primary flex items-center justify-center">
<i class="fas fa-chart-line text-white"></i>
</div>
<h1 class="text-xl font-bold text-dark">TeamPerf</h1>
</div>
<div class="flex items-center space-x-4">
<div class="relative">
<button id="notifications-btn" class="p-2 rounded-full hover:bg-gray-100">
<i class="fas fa-bell text-gray-500"></i>
<span id="notification-count" class="absolute top-0 right-0 w-5 h-5 bg-red-500 rounded-full text-white text-xs flex items-center justify-center">3</span>
</button>
<div id="notifications-dropdown" class="hidden absolute right-0 mt-2 w-64 bg-white rounded-md shadow-lg z-10">
<div class="p-4 border-b">
<h3 class="font-medium">Notifications</h3>
</div>
<div id="notification-list" class="max-h-60 overflow-y-auto">
<a href="#" class="block px-4 py-3 hover:bg-gray-50 border-b notification-item">
<p class="text-sm">John completed his quarterly goals</p>
<p class="text-xs text-gray-500">2 mins ago</p>
</a>
<a href="#" class="block px-4 py-3 hover:bg-gray-50 border-b notification-item">
<p class="text-sm">Sarah requested feedback</p>
<p class="text-xs text-gray-500">1 hour ago</p>
</a>
<a href="#" class="block px-4 py-3 hover:bg-gray-50 notification-item">
<p class="text-sm">New 360° review available</p>
<p class="text-xs text-gray-500">3 hours ago</p>
</a>
</div>
</div>
</div>
<div class="flex items-center space-x-2">
<img src="https://randomuser.me/api/portraits/women/44.jpg" alt="Profile" class="w-8 h-8 rounded-full">
<span class="text-sm font-medium">Jane D.</span>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-1">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<!-- Dashboard Header -->
<div class="flex justify-between items-center mb-6">
<div>
<h2 class="text-2xl font-bold text-dark">Performance Dashboard</h2>
<p class="text-gray-500">Track and manage your team's performance</p>
</div>
<div class="flex space-x-3">
<button id="new-goal-btn" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary-600 flex items-center">
<i class="fas fa-plus mr-2"></i> New Goal
</button>
<button id="filter-btn" class="px-4 py-2 bg-white border border-gray-300 rounded-md hover:bg-gray-50 flex items-center">
<i class="fas fa-filter mr-2"></i> Filter
</button>
</div>
</div>
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-6">
<div class="bg-white rounded-lg shadow p-6">
<div class="flex justify-between">
<div>
<p class="text-gray-500">Team Performance</p>
<h3 id="team-performance" class="text-2xl font-bold">82%</h3>
</div>
<div class="w-16 h-16">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path id="team-performance-ring" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#4F46E5"
stroke-width="3"
stroke-dasharray="82, 100"
/>
</svg>
</div>
</div>
<div class="mt-2 flex items-center text-sm text-gray-500">
<span class="text-green-500 mr-1"><i class="fas fa-arrow-up"></i> 5%</span>
<span>vs last quarter</span>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div class="flex justify-between">
<div>
<p class="text-gray-500">Goal Completion</p>
<h3 id="goal-completion" class="text-2xl font-bold">68%</h3>
</div>
<div class="w-16 h-16">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path id="goal-completion-ring" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="68, 100"
/>
</svg>
</div>
</div>
<div class="mt-2 flex items-center text-sm text-gray-500">
<span class="text-green-500 mr-1"><i class="fas fa-arrow-up"></i> 12%</span>
<span>vs last quarter</span>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div>
<p class="text-gray-500">Pending Reviews</p>
<h3 id="pending-reviews" class="text-2xl font-bold">14</h3>
</div>
<div class="mt-4">
<div class="flex justify-between text-sm mb-1">
<span>Overdue</span>
<span id="overdue-reviews">5</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div id="overdue-bar" class="bg-yellow-500 h-2 rounded-full" style="width: 35%"></div>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow p-6">
<div>
<p class="text-gray-500">Employee Engagement</p>
<h3 id="engagement-score" class="text-2xl font-bold">7.8</h3>
</div>
<div class="mt-4">
<div class="flex justify-between text-sm mb-1">
<span>eNPS Score</span>
<span id="enps-score">+42</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div id="engagement-bar" class="bg-purple-500 h-2 rounded-full" style="width: 78%"></div>
</div>
</div>
</div>
</div>
<!-- Main Content Area -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<!-- Left Column -->
<div class="lg:col-span-2 space-y-6">
<!-- Performance Trends Chart -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="font-bold text-lg">Performance Trends</h3>
<select id="time-period-select" class="border border-gray-300 rounded-md px-3 py-1 text-sm">
<option value="3">Last 3 Months</option>
<option value="6">Last 6 Months</option>
<option value="12">Last Year</option>
</select>
</div>
<div class="chart-container">
<canvas id="performanceChart"></canvas>
</div>
</div>
<!-- Team Goals -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="font-bold text-lg">Team Goals</h3>
<button id="view-all-goals" class="text-primary text-sm font-medium">View All</button>
</div>
<div id="goals-list" class="space-y-4">
<div class="border-b pb-4">
<div class="flex justify-between mb-2">
<h4 class="font-medium">Increase Customer Satisfaction</h4>
<span class="text-sm font-medium">75%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-primary h-2 rounded-full" style="width: 75%"></div>
</div>
<div class="flex justify-between mt-2 text-sm text-gray-500">
<span>Due: Jun 30, 2023</span>
<span>5/8 milestones</span>
</div>
</div>
<div class="border-b pb-4">
<div class="flex justify-between mb-2">
<h4 class="font-medium">Improve Product Quality</h4>
<span class="text-sm font-medium">62%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-primary h-2 rounded-full" style="width: 62%"></div>
</div>
<div class="flex justify-between mt-2 text-sm text-gray-500">
<span>Due: Aug 15, 2023</span>
<span>3/6 milestones</span>
</div>
</div>
<div>
<div class="flex justify-between mb-2">
<h4 class="font-medium">Expand Market Reach</h4>
<span class="text-sm font-medium">45%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-primary h-2 rounded-full" style="width: 45%"></div>
</div>
<div class="flex justify-between mt-2 text-sm text-gray-500">
<span>Due: Dec 31, 2023</span>
<span>2/5 milestones</span>
</div>
</div>
</div>
</div>
</div>
<!-- Right Column -->
<div class="space-y-6">
<!-- Quick Actions -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-bold text-lg mb-4">Quick Actions</h3>
<div class="grid grid-cols-2 gap-3">
<button id="set-goal-btn" class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50">
<div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mb-2">
<i class="fas fa-bullseye text-blue-600"></i>
</div>
<span class="text-sm">Set Goal</span>
</button>
<button id="give-feedback-btn" class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50">
<div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center mb-2">
<i class="fas fa-comment-alt text-green-600"></i>
</div>
<span class="text-sm">Give Feedback</span>
</button>
<button id="run-report-btn" class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50">
<div class="w-10 h-10 bg-purple-100 rounded-full flex items-center justify-center mb-2">
<i class="fas fa-chart-bar text-purple-600"></i>
</div>
<span class="text-sm">Run Report</span>
</button>
<button id="team-review-btn" class="flex flex-col items-center justify-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50">
<div class="w-10 h-10 bg-yellow-100 rounded-full flex items-center justify-center mb-2">
<i class="fas fa-users text-yellow-600"></i>
</div>
<span class="text-sm">Team Review</span>
</button>
</div>
</div>
<!-- Team Members -->
<div class="bg-white rounded-lg shadow p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="font-bold text-lg">Team Members</h3>
<button id="view-all-members" class="text-primary text-sm font-medium">View All</button>
</div>
<div id="team-members-list" class="space-y-4">
<div class="flex items-center">
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="Team member" class="w-10 h-10 rounded-full mr-3">
<div class="flex-1">
<h4 class="font-medium">John Smith</h4>
<p class="text-sm text-gray-500">Product Manager</p>
</div>
<div class="w-8 h-8">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path class="performance-ring" data-value="85" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="85, 100"
/>
</svg>
</div>
</div>
<div class="flex items-center">
<img src="https://randomuser.me/api/portraits/women/65.jpg" alt="Team member" class="w-10 h-10 rounded-full mr-3">
<div class="flex-1">
<h4 class="font-medium">Sarah Johnson</h4>
<p class="text-sm text-gray-500">UX Designer</p>
</div>
<div class="w-8 h-8">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path class="performance-ring" data-value="78" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="78, 100"
/>
</svg>
</div>
</div>
<div class="flex items-center">
<img src="https://randomuser.me/api/portraits/men/75.jpg" alt="Team member" class="w-10 h-10 rounded-full mr-3">
<div class="flex-1">
<h4 class="font-medium">Michael Chen</h4>
<p class="text-sm text-gray-500">Frontend Developer</p>
</div>
<div class="w-8 h-8">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path class="performance-ring" data-value="92" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="92, 100"
/>
</svg>
</div>
</div>
<div class="flex items-center">
<img src="https://randomuser.me/api/portraits/women/33.jpg" alt="Team member" class="w-10 h-10 rounded-full mr-3">
<div class="flex-1">
<h4 class="font-medium">Emily Wilson</h4>
<p class="text-sm text-gray-500">Marketing Specialist</p>
</div>
<div class="w-8 h-8">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path class="performance-ring" data-value="65" d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="65, 100"
/>
</svg>
</div>
</div>
</div>
</div>
<!-- Recent Feedback -->
<div class="bg-white rounded-lg shadow p-6">
<h3 class="font-bold text-lg mb-4">Recent Feedback</h3>
<div id="feedback-list" class="space-y-4">
<div class="flex">
<img src="https://randomuser.me/api/portraits/men/22.jpg" alt="Feedback giver" class="w-8 h-8 rounded-full mr-3">
<div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-sm">"Great job on the Q2 presentation! Your preparation really showed."</p>
</div>
<p class="text-xs text-gray-500 mt-1">David K. • 2 days ago</p>
</div>
</div>
<div class="flex">
<img src="https://randomuser.me/api/portraits/women/45.jpg" alt="Feedback giver" class="w-8 h-8 rounded-full mr-3">
<div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-sm">"Let's work on improving response times to customer inquiries."</p>
</div>
<p class="text-xs text-gray-500 mt-1">Lisa M. • 1 week ago</p>
</div>
</div>
</div>
<button id="view-all-feedback" class="mt-4 text-primary text-sm font-medium w-full text-center">View All Feedback</button>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- Modals -->
<div id="new-goal-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden modal">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold">Create New Goal</h3>
<button id="close-goal-modal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<form id="goal-form">
<div class="mb-4">
<label for="goal-title" class="block text-sm font-medium text-gray-700 mb-1">Goal Title</label>
<input type="text" id="goal-title" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
<div class="mb-4">
<label for="goal-description" class="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea id="goal-description" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary"></textarea>
</div>
<div class="grid grid-cols-2 gap-4 mb-4">
<div>
<label for="goal-due-date" class="block text-sm font-medium text-gray-700 mb-1">Due Date</label>
<input type="date" id="goal-due-date" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
<div>
<label for="goal-milestones" class="block text-sm font-medium text-gray-700 mb-1">Milestones</label>
<input type="number" id="goal-milestones" min="1" value="3" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
</div>
</div>
<div class="flex justify-end space-x-3">
<button type="button" id="cancel-goal" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300">Cancel</button>
<button type="submit" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary-600">Create Goal</button>
</div>
</form>
</div>
</div>
</div>
<div id="feedback-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden modal">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold">Give Feedback</h3>
<button id="close-feedback-modal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<form id="feedback-form">
<div class="mb-4">
<label for="feedback-recipient" class="block text-sm font-medium text-gray-700 mb-1">Recipient</label>
<select id="feedback-recipient" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
<option value="">Select team member</option>
<option value="John Smith">John Smith</option>
<option value="Sarah Johnson">Sarah Johnson</option>
<option value="Michael Chen">Michael Chen</option>
<option value="Emily Wilson">Emily Wilson</option>
</select>
</div>
<div class="mb-4">
<label for="feedback-type" class="block text-sm font-medium text-gray-700 mb-1">Feedback Type</label>
<select id="feedback-type" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary">
<option value="positive">Positive</option>
<option value="constructive">Constructive</option>
<option value="development">Development</option>
</select>
</div>
<div class="mb-4">
<label for="feedback-message" class="block text-sm font-medium text-gray-700 mb-1">Message</label>
<textarea id="feedback-message" rows="4" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary"></textarea>
</div>
<div class="flex justify-end space-x-3">
<button type="button" id="cancel-feedback" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300">Cancel</button>
<button type="submit" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary-600">Submit Feedback</button>
</div>
</form>
</div>
</div>
</div>
<div id="view-all-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden modal">
<div class="bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] flex flex-col">
<div class="p-6 border-b">
<div class="flex justify-between items-center">
<h3 id="view-all-title" class="text-lg font-bold">View All</h3>
<button id="close-view-all-modal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<div id="view-all-content" class="p-6 overflow-y-auto flex-1">
<!-- Content will be dynamically inserted here -->
</div>
</div>
</div>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Dashboard Data
const dashboardData = {
teamPerformance: 82,
goalCompletion: 68,
pendingReviews: 14,
overdueReviews: 5,
engagementScore: 7.8,
enpsScore: 42,
performanceTrends: {
'3': {
labels: ['Apr', 'May', 'Jun'],
team: [80, 79, 82],
goals: [65, 67, 68]
},
'6': {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
team: [72, 75, 78, 80, 79, 82],
goals: [58, 60, 62, 65, 67, 68]
},
'12': {
labels: ['Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
team: [65, 68, 70, 72, 70, 72, 72, 75, 78, 80, 79, 82],
goals: [50, 52, 55, 56, 55, 56, 58, 60, 62, 65, 67, 68]
}
},
teamGoals: [
{
title: "Increase Customer Satisfaction",
progress: 75,
dueDate: "Jun 30, 2023",
milestones: "5/8"
},
{
title: "Improve Product Quality",
progress: 62,
dueDate: "Aug 15, 2023",
milestones: "3/6"
},
{
title: "Expand Market Reach",
progress: 45,
dueDate: "Dec 31, 2023",
milestones: "2/5"
},
{
title: "Reduce Operational Costs",
progress: 30,
dueDate: "Sep 30, 2023",
milestones: "1/4"
},
{
title: "Improve Employee Retention",
progress: 55,
dueDate: "Nov 15, 2023",
milestones: "4/7"
}
],
teamMembers: [
{
name: "John Smith",
role: "Product Manager",
performance: 85,
photo: "https://randomuser.me/api/portraits/men/32.jpg"
},
{
name: "Sarah Johnson",
role: "UX Designer",
performance: 78,
photo: "https://randomuser.me/api/portraits/women/65.jpg"
},
{
name: "Michael Chen",
role: "Frontend Developer",
performance: 92,
photo: "https://randomuser.me/api/portraits/men/75.jpg"
},
{
name: "Emily Wilson",
role: "Marketing Specialist",
performance: 65,
photo: "https://randomuser.me/api/portraits/women/33.jpg"
},
{
name: "David Kim",
role: "Backend Developer",
performance: 88,
photo: "https://randomuser.me/api/portraits/men/22.jpg"
},
{
name: "Lisa Martinez",
role: "QA Engineer",
performance: 72,
photo: "https://randomuser.me/api/portraits/women/45.jpg"
}
],
feedback: [
{
giver: "David K.",
message: "Great job on the Q2 presentation! Your preparation really showed.",
date: "2 days ago",
photo: "https://randomuser.me/api/portraits/men/22.jpg"
},
{
giver: "Lisa M.",
message: "Let's work on improving response times to customer inquiries.",
date: "1 week ago",
photo: "https://randomuser.me/api/portraits/women/45.jpg"
},
{
giver: "Robert T.",
message: "Your attention to detail in the last sprint was excellent.",
date: "2 weeks ago",
photo: "https://randomuser.me/api/portraits/men/41.jpg"
},
{
giver: "Anna S.",
message: "The new onboarding process you designed is very effective.",
date: "3 weeks ago",
photo: "https://randomuser.me/api/portraits/women/63.jpg"
}
],
notifications: [
{
message: "John completed his quarterly goals",
time: "2 mins ago"
},
{
message: "Sarah requested feedback",
time: "1 hour ago"
},
{
message: "New 360° review available",
time: "3 hours ago"
}
]
};
// Initialize dashboard
document.addEventListener('DOMContentLoaded', function() {
// Initialize charts and data
initPerformanceChart();
updateDashboardData();
initEventListeners();
// Add fade-in animation to all cards
const cards = document.querySelectorAll('.bg-white');
cards.forEach((card, index) => {
card.classList.add('fade-in');
card.style.animationDelay = `${index * 0.1}s`;
});
});
// Initialize performance chart
let performanceChart;
function initPerformanceChart() {
const ctx = document.getElementById('performanceChart').getContext('2d');
const selectedPeriod = document.getElementById('time-period-select').value;
const data = dashboardData.performanceTrends[selectedPeriod];
performanceChart = new Chart(ctx, {
type: 'line',
data: {
labels: data.labels,
datasets: [
{
label: 'Team Performance',
data: data.team,
borderColor: '#4F46E5',
backgroundColor: 'rgba(79, 70, 229, 0.1)',
borderWidth: 2,
tension: 0.3,
fill: true
},
{
label: 'Goal Completion',
data: data.goals,
borderColor: '#10B981',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
borderWidth: 2,
tension: 0.3,
fill: true
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
},
tooltip: {
mode: 'index',
intersect: false,
}
},
scales: {
y: {
beginAtZero: false,
min: 50,
max: 100,
ticks: {
stepSize: 10
}
}
}
}
});
}
// Update dashboard data
function updateDashboardData() {
// Update metrics
document.getElementById('team-performance').textContent = `${dashboardData.teamPerformance}%`;
document.getElementById('goal-completion').textContent = `${dashboardData.goalCompletion}%`;
document.getElementById('pending-reviews').textContent = dashboardData.pendingReviews;
document.getElementById('overdue-reviews').textContent = dashboardData.overdueReviews;
document.getElementById('engagement-score').textContent = dashboardData.engagementScore;
document.getElementById('enps-score').textContent = `+${dashboardData.enpsScore}`;
// Update progress rings
document.getElementById('team-performance-ring').setAttribute('stroke-dasharray', `${dashboardData.teamPerformance}, 100`);
document.getElementById('goal-completion-ring').setAttribute('stroke-dasharray', `${dashboardData.goalCompletion}, 100`);
// Update progress bars
document.getElementById('overdue-bar').style.width = `${(dashboardData.overdueReviews / dashboardData.pendingReviews) * 100}%`;
document.getElementById('engagement-bar').style.width = `${(dashboardData.engagementScore / 10) * 100}%`;
// Update team member performance rings
document.querySelectorAll('.performance-ring').forEach(ring => {
const value = ring.getAttribute('data-value');
ring.setAttribute('stroke-dasharray', `${value}, 100`);
});
}
// Initialize event listeners
function initEventListeners() {
// Notifications dropdown
document.getElementById('notifications-btn').addEventListener('click', function(e) {
e.stopPropagation();
const dropdown = document.getElementById('notifications-dropdown');
dropdown.classList.toggle('hidden');
});
// Close dropdown when clicking outside
document.addEventListener('click', function() {
document.getElementById('notifications-dropdown').classList.add('hidden');
});
// Time period selector
document.getElementById('time-period-select').addEventListener('change', function() {
performanceChart.destroy();
initPerformanceChart();
});
// New goal modal
document.getElementById('new-goal-btn').addEventListener('click', function() {
document.getElementById('new-goal-modal').classList.remove('hidden');
});
document.getElementById('close-goal-modal').addEventListener('click', function() {
document.getElementById('new-goal-modal').classList.add('hidden');
});
document.getElementById('cancel-goal').addEventListener('click', function() {
document.getElementById('new-goal-modal').classList.add('hidden');
});
document.getElementById('goal-form').addEventListener('submit', function(e) {
e.preventDefault();
const title = document.getElementById('goal-title').value;
const description = document.getElementById('goal-description').value;
const dueDate = document.getElementById('goal-due-date').value;
const milestones = document.getElementById('goal-milestones').value;
// Format date
const formattedDate = new Date(dueDate).toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
// Add new goal
const newGoal = {
title: title,
progress: 0,
dueDate: formattedDate,
milestones: `0/${milestones}`
};
dashboardData.teamGoals.unshift(newGoal);
updateGoalsList();
// Update goal completion metric
const totalGoals = dashboardData.teamGoals.length;
const completedGoals = dashboardData.teamGoals.filter(g => g.progress === 100).length;
dashboardData.goalCompletion = Math.round((completedGoals / totalGoals) * 100);
updateDashboardData();
// Reset form and close modal
document.getElementById('goal-form').reset();
document.getElementById('new-goal-modal').classList.add('hidden');
// Show success message
alert('New goal created successfully!');
});
// Feedback modal
document.getElementById('give-feedback-btn').addEventListener('click', function() {
document.getElementById('feedback-modal').classList.remove('hidden');
});
document.getElementById('close-feedback-modal').addEventListener('click', function() {
document.getElementById('feedback-modal').classList.add('hidden');
});
document.getElementById('cancel-feedback').addEventListener('click', function() {
document.getElementById('feedback-modal').classList.add('hidden');
});
document.getElementById('feedback-form').addEventListener('submit', function(e) {
e.preventDefault();
const recipient = document.getElementById('feedback-recipient').value;
const type = document.getElementById('feedback-type').value;
const message = document.getElementById('feedback-message').value;
// Add new feedback
const newFeedback = {
giver: "You",
message: message,
date: "Just now",
photo: "https://randomuser.me/api/portraits/women/44.jpg",
type: type,
recipient: recipient
};
dashboardData.feedback.unshift(newFeedback);
updateFeedbackList();
// Reset form and close modal
document.getElementById('feedback-form').reset();
document.getElementById('feedback-modal').classList.add('hidden');
// Show success message
alert('Feedback submitted successfully!');
});
// View all modals
document.getElementById('view-all-goals').addEventListener('click', function() {
showViewAllModal('Team Goals', 'goals');
});
document.getElementById('view-all-members').addEventListener('click', function() {
showViewAllModal('Team Members', 'members');
});
document.getElementById('view-all-feedback').addEventListener('click', function() {
showViewAllModal('All Feedback', 'feedback');
});
document.getElementById('close-view-all-modal').addEventListener('click', function() {
document.getElementById('view-all-modal').classList.add('hidden');
});
// Quick action buttons
document.getElementById('set-goal-btn').addEventListener('click', function() {
document.getElementById('new-goal-modal').classList.remove('hidden');
});
document.getElementById('run-report-btn').addEventListener('click', function() {
alert('Performance report is being generated. You will receive a notification when it\'s ready.');
});
document.getElementById('team-review-btn').addEventListener('click', function() {
alert('Team review session has been scheduled for next Monday at 10 AM.');
});
// Filter button
document.getElementById('filter-btn').addEventListener('click', function() {
alert('Filter functionality will be implemented in the next version.');
});
// Notification items
document.querySelectorAll('.notification-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const index = Array.from(document.querySelectorAll('.notification-item')).indexOf(item);
dashboardData.notifications.splice(index, 1);
updateNotificationList();
// Close dropdown
document.getElementById('notifications-dropdown').classList.add('hidden');
});
});
}
// Update goals list
function updateGoalsList() {
const goalsList = document.getElementById('goals-list');
goalsList.innerHTML = '';
// Show only first 3 goals in the main view
const goalsToShow = dashboardData.teamGoals.slice(0, 3);
goalsToShow.forEach(goal => {
const goalElement = document.createElement('div');
goalElement.className = 'border-b pb-4';
goalElement.innerHTML = `
<div class="flex justify-between mb-2">
<h4 class="font-medium">${goal.title}</h4>
<span class="text-sm font-medium">${goal.progress}%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-primary h-2 rounded-full" style="width: ${goal.progress}%"></div>
</div>
<div class="flex justify-between mt-2 text-sm text-gray-500">
<span>Due: ${goal.dueDate}</span>
<span>${goal.milestones} milestones</span>
</div>
`;
goalsList.appendChild(goalElement);
});
}
// Update feedback list
function updateFeedbackList() {
const feedbackList = document.getElementById('feedback-list');
feedbackList.innerHTML = '';
// Show only first 2 feedback items in the main view
const feedbackToShow = dashboardData.feedback.slice(0, 2);
feedbackToShow.forEach(feedback => {
const feedbackElement = document.createElement('div');
feedbackElement.className = 'flex';
feedbackElement.innerHTML = `
<img src="${feedback.photo}" alt="Feedback giver" class="w-8 h-8 rounded-full mr-3">
<div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-sm">"${feedback.message}"</p>
</div>
<p class="text-xs text-gray-500 mt-1">${feedback.giver}${feedback.date}</p>
</div>
`;
feedbackList.appendChild(feedbackElement);
});
}
// Update notification list
function updateNotificationList() {
const notificationList = document.getElementById('notification-list');
notificationList.innerHTML = '';
dashboardData.notifications.forEach(notification => {
const notificationElement = document.createElement('a');
notificationElement.href = '#';
notificationElement.className = 'block px-4 py-3 hover:bg-gray-50 border-b notification-item';
notificationElement.innerHTML = `
<p class="text-sm">${notification.message}</p>
<p class="text-xs text-gray-500">${notification.time}</p>
`;
notificationList.appendChild(notificationElement);
});
// Update notification count
document.getElementById('notification-count').textContent = dashboardData.notifications.length;
// Add event listeners to new notification items
document.querySelectorAll('.notification-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
const index = Array.from(document.querySelectorAll('.notification-item')).indexOf(item);
dashboardData.notifications.splice(index, 1);
updateNotificationList();
// Close dropdown
document.getElementById('notifications-dropdown').classList.add('hidden');
});
});
}
// Show view all modal
function showViewAllModal(title, type) {
document.getElementById('view-all-title').textContent = title;
const content = document.getElementById('view-all-content');
content.innerHTML = '';
if (type === 'goals') {
dashboardData.teamGoals.forEach(goal => {
const goalElement = document.createElement('div');
goalElement.className = 'border-b pb-4 mb-4';
goalElement.innerHTML = `
<div class="flex justify-between mb-2">
<h4 class="font-medium">${goal.title}</h4>
<span class="text-sm font-medium">${goal.progress}%</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-2">
<div class="bg-primary h-2 rounded-full" style="width: ${goal.progress}%"></div>
</div>
<div class="flex justify-between mt-2 text-sm text-gray-500">
<span>Due: ${goal.dueDate}</span>
<span>${goal.milestones} milestones</span>
</div>
`;
content.appendChild(goalElement);
});
} else if (type === 'members') {
dashboardData.teamMembers.forEach(member => {
const memberElement = document.createElement('div');
memberElement.className = 'flex items-center mb-4';
memberElement.innerHTML = `
<img src="${member.photo}" alt="Team member" class="w-10 h-10 rounded-full mr-3">
<div class="flex-1">
<h4 class="font-medium">${member.name}</h4>
<p class="text-sm text-gray-500">${member.role}</p>
</div>
<div class="w-8 h-8">
<svg class="w-full h-full" viewBox="0 0 36 36">
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#E5E7EB"
stroke-width="3"
stroke-dasharray="100, 100"
/>
<path d="M18 2.0845
a 15.9155 15.9155 0 0 1 0 31.831
a 15.9155 15.9155 0 0 1 0 -31.831"
fill="none"
stroke="#10B981"
stroke-width="3"
stroke-dasharray="${member.performance}, 100"
/>
</svg>
</div>
`;
content.appendChild(memberElement);
});
} else if (type === 'feedback') {
dashboardData.feedback.forEach(feedback => {
const feedbackElement = document.createElement('div');
feedbackElement.className = 'border-b pb-4 mb-4';
feedbackElement.innerHTML = `
<div class="flex">
<img src="${feedback.photo}" alt="Feedback giver" class="w-8 h-8 rounded-full mr-3">
<div class="flex-1">
<div class="flex justify-between items-center mb-1">
<h4 class="font-medium">${feedback.giver}</h4>
<span class="text-xs text-gray-500">${feedback.date}</span>
</div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-sm">"${feedback.message}"</p>
</div>
${feedback.recipient ? `<p class="text-xs text-gray-500 mt-1">To: ${feedback.recipient}</p>` : ''}
</div>
</div>
`;
content.appendChild(feedbackElement);
});
}
document.getElementById('view-all-modal').classList.remove('hidden');
}
// Simulate data updates (for demo purposes)
setInterval(function() {
// Randomly update some metrics
dashboardData.teamPerformance = Math.min(100, dashboardData.teamPerformance + (Math.random() > 0.5 ? 1 : -1));
dashboardData.goalCompletion = Math.min(100, dashboardData.goalCompletion + (Math.random() > 0.5 ? 1 : -1));
dashboardData.engagementScore = (Math.random() * 0.2 + 7.6).toFixed(1);
// Update dashboard
updateDashboardData();
// Occasionally add a notification
if (Math.random() > 0.9 && dashboardData.notifications.length < 5) {
const messages = [
"New performance review available",
"Team meeting in 15 minutes",
"Quarterly report is ready",
"Goal progress update",
"New feedback received"
];
const times = [
"Just now",
"1 min ago",
"5 mins ago"
];
dashboardData.notifications.push({
message: messages[Math.floor(Math.random() * messages.length)],
time: times[Math.floor(Math.random() * times.length)]
});
updateNotificationList();
}
}, 5000);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=JayStormX8/team-goals" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>