-
Notifications
You must be signed in to change notification settings - Fork 0
/
work_dashboard.php
361 lines (288 loc) · 14.1 KB
/
work_dashboard.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
<?php
// Enable error reporting
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Set up error logging
$logFile = 'error_log.txt';
ini_set('log_errors', 1);
ini_set('error_log', $logFile);
// Function to read CSV data and return it as an array
function readCsvData($filename) {
if (!file_exists($filename)) {
error_log("Error: File not found - $filename");
return [];
}
$file = fopen($filename, "r");
if (!$file) {
error_log("Error: Could not open file - $filename");
return [];
}
$data = [];
while (($row = fgetcsv($file)) !== FALSE) {
$data[] = $row;
}
fclose($file);
return $data;
}
// Directory containing the CSV files
$csvDirectory = "WORK_RECORD_DB";
// Mapping of team member HTML card IDs to their respective CSV files
$teamMembers = [
"nexus_prime" => "nexus_prime_rsz2546qv1.csv",
"echo_volt" => "echo_volt_rsz8739tx2.csv",
"vortex_blaze" => "vortex_blaze_rsz9145yl8.csv",
"orion_flux" => "orion_flux_rsz6328mw4.csv"
];
// Initialize an array to store the data for each team member
$teamData = [];
// Loop through each team member and read their respective CSV file
foreach ($teamMembers as $memberId => $csvFile) {
$filePath = $csvDirectory . '/' . $csvFile;
if (file_exists($filePath)) {
$teamData[$memberId] = readCsvData($filePath);
} else {
$teamData[$memberId] = [];
}
}
// Function to calculate the total work tokens, weekly and monthly average working hours
function calculateMetrics($data) {
$totalTokens = count($data);
$totalHours = 0;
$weeklyAverage = 0;
$monthlyAverage = 0;
$labels = [];
$lastSubmission = "N/A";
// Initialize start date for range calculations
$startDate = null;
foreach ($data as $row) {
$totalHours += (float)$row[3];
$labels[] = $row[2];
// Assuming the last row in the CSV is the most recent submission
$lastSubmission = $row[4];
// Determine the start date
$entryDate = new DateTime($row[4]);
if ($startDate === null || $entryDate < $startDate) {
$startDate = $entryDate;
}
}
if ($startDate === null) {
error_log("Error: No valid start date found.");
return [
"last_submission" => $lastSubmission,
"total_tokens" => $totalTokens,
"weekly_average" => "N/A",
"monthly_average" => "N/A",
"top_labels" => implode(", ", array_slice(array_keys(array_count_values($labels)), 0, 5))
];
}
// Calculate total days between the start date and current date
$endDate = new DateTime();
$totalDays = $endDate->diff($startDate)->days;
// Initialize default values
$showWeeklyAverage = false;
$showMonthlyAverage = false;
// Calculate the total number of weeks and months
$totalWeeks = ceil($totalDays / 7);
$totalMonths = ceil($totalDays / 30);
// Check if 7 days have passed for weekly average
if ($totalDays >= 7) {
$showWeeklyAverage = true;
$weeklyAverage = $totalHours / $totalWeeks;
}
// Check if 30 days have passed for monthly average
if ($totalDays >= 30) {
$showMonthlyAverage = true;
$monthlyAverage = $totalHours / $totalMonths;
}
// Get the top 5 most common labels
$labelCounts = array_count_values($labels);
arsort($labelCounts);
$topLabels = array_slice(array_keys($labelCounts), 0, 5);
return [
"last_submission" => $lastSubmission,
"total_tokens" => $totalTokens,
"weekly_average" => $showWeeklyAverage ? round($weeklyAverage, 2) : "N/A",
"monthly_average" => $showMonthlyAverage ? round($monthlyAverage, 2) : "N/A",
"top_labels" => implode(", ", $topLabels)
];
}
?>
<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> Dashboard </title>
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp"></script>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
</head>
<body>
<!--Header section-->
<header class="body-font bg-gradient-to-r from-cyan-500 via-teal-400 to-teal-0 shadow-md">
<div class="container mx-auto flex flex-wrap p-2 items-center justify-between">
<a href="index.html" class="flex title-font font-medium items-center text-gray-900 mb-4 md:mb-0">
<img alt="logo0"
class="w-24 h-24 object-cover object-center rounded-full inline-block items-center justify-center bg-white"
src="https://dummyimage.com/80x80">
<h1 class="ml-3 mt-5 sm:text-3xl text-2xl font-medium title-font font-sans mb-4 text-blue-900">Company Name: Dashboard </h1>
</a>
</div>
</header>
<!--Team description-->
<section class="body-font">
<div class="container px-5 py-12 mx-auto">
<div class="flex flex-col text-center w-full mb-10" data-aos="fade-up" data-aos-duration="500">
<h1 class="text-4xl md:text-5xl font-bold title-font text-teal-500 mb-6">Dashboard</h1>
<p>To track your contributions and performance. Create and manage them through the dashboard for efficient monitoring and evaluation.</p>
</div>
</div>
</section>
<!-- Team Member Section -->
<section id="our-team" class="relative bg-gray-100 py-4 mb-10">
<div class="container max-w-screen-xl mx-auto px-4 mb-10">
<!-- Add portal button -->
<div class="flex justify-end mt-2">
<a href="index.html" target="_blank">
<button class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-md mt-2 mb-6"> Add work token </button>
</a>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- Team Member Cards will be generated by PHP -->
<?php foreach ($teamMembers as $memberId => $csvFile): ?>
<?php $metrics = calculateMetrics($teamData[$memberId]); ?>
<div class="bg-white w-full rounded-lg shadow-md p-6 my-6 text-center hover:-translate-y-1 hover:scale-105 duration-300" id="<?php echo $memberId; ?>">
<img src="<?php echo $memberId; ?>.png" alt="Team Member" class="w-full rounded-full mb-4">
<h3 class="text-xl font-semibold mb-2"><?php echo ucwords(str_replace("_", " ", $memberId)); ?></h3>
<div class="text-gray-800 text-md px-4 w-full">
<ul class="w-full">
<li class="inline-block mx-4 mb-2 text-left">
<h1 class="text-gray-900 font-base py-2 font-bold">Highlights</h1>
<h1>Last submission: <?php echo $metrics["last_submission"]; ?></h1>
<h1>Work tokens: <?php echo $metrics["total_tokens"]; ?></h1>
<h1>Weekly Avg : <?php echo $metrics["weekly_average"]; ?> hr</h1>
<h1>Monthly Avg: <?php echo $metrics["monthly_average"]; ?> hr</h1>
<h1>Most work includes: <br/> <?php echo $metrics["top_labels"]; ?></h1>
</li>
</ul>
</div>
<button class="bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-md mt-4" onclick="showDetails('<?php echo $memberId; ?>')">
View Details
</button>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
<!-- Hidden div for view details -->
<div class="bg-white hidden" id="details-container">
<div class="max-w-xl mx-auto p-8">
<h2 id="member-name" class="text-2xl font-semibold mb-2">Member Name</h2> <!-- Placeholder for member's name -->
<h2 class="text-xl font-semibold mb-4">( work log / tokens )</h2>
<div class="flow-root">
<ul id="work-details-list" class="-mb-8">
<!-- Work details of the team member will be inserted here -->
</ul>
</div>
</div>
</div>
<script>
// Function to show the details of a specific team member
function showDetails(memberId) {
// Hide the details container first
document.getElementById('details-container').classList.add('hidden');
// Clear any existing details
document.getElementById('work-details-list').innerHTML = '';
// Load the work details for the selected team member
var teamData = <?php echo json_encode($teamData); ?>;
var workDetails = teamData[memberId];
// Reverse the order to show the latest work on top
workDetails.reverse();
// Update the member name at the top
var memberName = memberId.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase()); // replaces all underscores and capitalizes the first letter of each word
var nameElement = document.getElementById('member-name');
if (nameElement) {
nameElement.textContent = memberName;
}
// Generate the list items for work details
workDetails.forEach(function(detail) {
var listItem = `
<li>
<div class="relative pb-8">
<span class="absolute top-5 left-5 -ml-px h-full w-0.5 bg-gray-200" aria-hidden="true"></span>
<div class="relative flex items-start space-x-3">
<div>
<div class="relative px-1">
<div class="h-8 w-8 bg-blue-500 rounded-full ring-8 ring-white flex items-center justify-center">
<svg class="text-white h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
</div>
</div>
</div>
<div class="min-w-0 flex-1 py-0">
<div class="text-md text-gray-500">
<div>
<a class="font-medium text-gray-900 mr-2">${detail[0]}</a>
<a class="my-0.5 relative inline-flex items-center bg-white rounded-full border border-gray-300 px-3 py-0.5 text-sm">
<div class="absolute flex-shrink-0 flex items-center justify-center">
<span class="h-1.5 w-1.5 rounded-full bg-green-500" aria-hidden="true"></span>
</div>
<div class="ml-3.5 font-medium text-gray-900">${detail[2]}</div>
</a>
</div>
<span class="whitespace-nowrap text-sm">On ${detail[4]}</span>, <span class="whitespace-nowrap text-sm">Work Duration ${detail[3]} hr</span> <!-- duration -->
</div>
<div class="mt-2 text-gray-700">
<p>${detail[1]}</p>
</div>
</div>
</div>
</div>
</li>
`;
document.getElementById('work-details-list').innerHTML += listItem;
});
// Show the details container
document.getElementById('details-container').classList.remove('hidden');
}
</script>
<!-- Footer section -->
<footer class="relative bg-teal-500 text-white">
<div class="pt-20 mx-auto max-w-screen-xl">
<div class="md:flex md:justify-between m-5 text-center justify-center items-center flex-row">
<div class="mb-6 md:mb-0 mt-6">
<a href="index.html" class="flex items-center">
<img alt="logo0"
class="w-24 h-24 object-cover object-center rounded-full inline-block items-center justify-center bg-white"
src="https://dummyimage.com/80x80">
<span
class="self-center text-2xl font-medium title-font font-sans whitespace-nowrap ms-5 text-wrap">Company Name</span>
</a>
</div>
<div>
<h2 class="mb-4 text-md font-semibold text-white uppercase">News & Events</h2>
<ul class="text-white">
<li class="mb-4">
<a href="#" class="hover:underline"><i class="fa-solid fa-newspaper"></i> News</a>
</li>
<li class="mb-4">
<a href="#" class="hover:underline"><i class="fa-solid fa-chart-line"></i> Annual
Report</a>
</li>
<li class="mb-4">
<a href="#" class="hover:underline"><i class="fa-solid fa-image"></i> Gallery</a>
</li>
</ul>
</div>
</div>
</div>
<hr class="border-gray-200 sm:mx-auto lg:mb-3" />
<div class="sm:flex sm:items-center sm:justify-center text-center">
<span class="text-sm text-white text-center">© 2024 WorkLog-Tracker ( Github )</span>
</div>
</div>
</footer>
</body>
</html>