aaronxavier commited on
Commit
0b5ed69
·
verified ·
1 Parent(s): dbdaaec

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +586 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Energytracker
3
- emoji: 👀
4
  colorFrom: gray
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: energytracker
3
+ emoji: 🐳
4
  colorFrom: gray
5
+ colorTo: blue
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,586 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Energy Consumption Tracker</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .gradient-bg {
11
+ background: linear-gradient(135deg, #6b73ff 0%, #000dff 100%);
12
+ }
13
+ .reading-card:hover {
14
+ transform: translateY(-5px);
15
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
16
+ }
17
+ .chart-container {
18
+ height: 300px;
19
+ }
20
+ @keyframes pulse {
21
+ 0%, 100% {
22
+ opacity: 1;
23
+ }
24
+ 50% {
25
+ opacity: 0.5;
26
+ }
27
+ }
28
+ .animate-pulse {
29
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
30
+ }
31
+ </style>
32
+ </head>
33
+ <body class="bg-gray-50 min-h-screen">
34
+ <!-- Header -->
35
+ <header class="gradient-bg text-white shadow-lg">
36
+ <div class="container mx-auto px-4 py-6">
37
+ <div class="flex justify-between items-center">
38
+ <div class="flex items-center space-x-3">
39
+ <i class="fas fa-bolt text-2xl"></i>
40
+ <h1 class="text-2xl font-bold">EnergyTracker</h1>
41
+ </div>
42
+ <div class="hidden md:flex space-x-6">
43
+ <a href="#" class="hover:text-blue-200 transition">Dashboard</a>
44
+ <a href="#" class="hover:text-blue-200 transition">History</a>
45
+ <a href="#" class="hover:text-blue-200 transition">Reports</a>
46
+ <a href="#" class="hover:text-blue-200 transition">Settings</a>
47
+ </div>
48
+ <button class="md:hidden text-xl">
49
+ <i class="fas fa-bars"></i>
50
+ </button>
51
+ </div>
52
+ </div>
53
+ </header>
54
+
55
+ <!-- Main Content -->
56
+ <main class="container mx-auto px-4 py-8">
57
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
58
+ <!-- Input Form -->
59
+ <div class="lg:col-span-1 bg-white rounded-xl shadow-md p-6">
60
+ <h2 class="text-xl font-semibold mb-4 text-gray-800">Add New Reading</h2>
61
+ <form id="readingForm" class="space-y-4">
62
+ <div>
63
+ <label for="readingDate" class="block text-sm font-medium text-gray-700 mb-1">Date</label>
64
+ <input type="date" id="readingDate" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" value="">
65
+ </div>
66
+ <div>
67
+ <label for="meterReading" class="block text-sm font-medium text-gray-700 mb-1">Meter Reading (kWh)</label>
68
+ <input type="number" step="0.01" id="meterReading" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter current reading">
69
+ </div>
70
+ <div>
71
+ <label for="meterType" class="block text-sm font-medium text-gray-700 mb-1">Meter Type</label>
72
+ <select id="meterType" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
73
+ <option value="electricity">Electricity</option>
74
+ <option value="gas">Gas</option>
75
+ <option value="water">Water</option>
76
+ </select>
77
+ </div>
78
+ <div>
79
+ <label for="notes" class="block text-sm font-medium text-gray-700 mb-1">Notes</label>
80
+ <textarea id="notes" rows="3" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Any additional notes"></textarea>
81
+ </div>
82
+ <button type="submit" class="w-full gradient-bg text-white py-3 px-4 rounded-lg font-medium hover:opacity-90 transition flex items-center justify-center space-x-2">
83
+ <i class="fas fa-save"></i>
84
+ <span>Save Reading</span>
85
+ </button>
86
+ </form>
87
+ </div>
88
+
89
+ <!-- Dashboard -->
90
+ <div class="lg:col-span-2 space-y-6">
91
+ <!-- Summary Cards -->
92
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
93
+ <div class="bg-white rounded-xl shadow-md p-4 flex items-center">
94
+ <div class="p-3 rounded-full bg-blue-100 text-blue-600 mr-4">
95
+ <i class="fas fa-bolt text-xl"></i>
96
+ </div>
97
+ <div>
98
+ <p class="text-sm text-gray-500">Current Month</p>
99
+ <h3 class="text-xl font-semibold" id="currentMonthUsage">-- kWh</h3>
100
+ </div>
101
+ </div>
102
+ <div class="bg-white rounded-xl shadow-md p-4 flex items-center">
103
+ <div class="p-3 rounded-full bg-green-100 text-green-600 mr-4">
104
+ <i class="fas fa-chart-line text-xl"></i>
105
+ </div>
106
+ <div>
107
+ <p class="text-sm text-gray-500">Avg Daily Usage</p>
108
+ <h3 class="text-xl font-semibold" id="avgDailyUsage">-- kWh</h3>
109
+ </div>
110
+ </div>
111
+ <div class="bg-white rounded-xl shadow-md p-4 flex items-center">
112
+ <div class="p-3 rounded-full bg-purple-100 text-purple-600 mr-4">
113
+ <i class="fas fa-calendar-alt text-xl"></i>
114
+ </div>
115
+ <div>
116
+ <p class="text-sm text-gray-500">Projected Month</p>
117
+ <h3 class="text-xl font-semibold" id="projectedUsage">-- kWh</h3>
118
+ </div>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Chart -->
123
+ <div class="bg-white rounded-xl shadow-md p-6">
124
+ <div class="flex justify-between items-center mb-4">
125
+ <h2 class="text-lg font-semibold text-gray-800">Consumption Trend</h2>
126
+ <div class="flex space-x-2">
127
+ <button class="px-3 py-1 text-sm bg-blue-100 text-blue-600 rounded-lg">Monthly</button>
128
+ <button class="px-3 py-1 text-sm bg-gray-100 text-gray-600 rounded-lg">Yearly</button>
129
+ </div>
130
+ </div>
131
+ <div class="chart-container">
132
+ <canvas id="consumptionChart"></canvas>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Recent Readings -->
137
+ <div class="bg-white rounded-xl shadow-md p-6">
138
+ <h2 class="text-lg font-semibold text-gray-800 mb-4">Recent Readings</h2>
139
+ <div class="overflow-x-auto">
140
+ <table class="min-w-full divide-y divide-gray-200">
141
+ <thead class="bg-gray-50">
142
+ <tr>
143
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
144
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Type</th>
145
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Reading</th>
146
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Daily Avg</th>
147
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
148
+ </tr>
149
+ </thead>
150
+ <tbody id="readingsTableBody" class="bg-white divide-y divide-gray-200">
151
+ <!-- Readings will be inserted here by JavaScript -->
152
+ <tr>
153
+ <td colspan="5" class="px-6 py-4 text-center text-gray-500">No readings yet. Add your first reading!</td>
154
+ </tr>
155
+ </tbody>
156
+ </table>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </div>
161
+ </main>
162
+
163
+ <!-- Modal for editing -->
164
+ <div id="editModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden">
165
+ <div class="bg-white rounded-xl p-6 w-full max-w-md">
166
+ <div class="flex justify-between items-center mb-4">
167
+ <h3 class="text-lg font-semibold">Edit Reading</h3>
168
+ <button id="closeModal" class="text-gray-500 hover:text-gray-700">
169
+ <i class="fas fa-times"></i>
170
+ </button>
171
+ </div>
172
+ <form id="editForm" class="space-y-4">
173
+ <input type="hidden" id="editId">
174
+ <div>
175
+ <label for="editDate" class="block text-sm font-medium text-gray-700 mb-1">Date</label>
176
+ <input type="date" id="editDate" class="w-full px-4 py-2 border border-gray-300 rounded-lg">
177
+ </div>
178
+ <div>
179
+ <label for="editReading" class="block text-sm font-medium text-gray-700 mb-1">Reading (kWh)</label>
180
+ <input type="number" step="0.01" id="editReading" class="w-full px-4 py-2 border border-gray-300 rounded-lg">
181
+ </div>
182
+ <div>
183
+ <label for="editType" class="block text-sm font-medium text-gray-700 mb-1">Meter Type</label>
184
+ <select id="editType" class="w-full px-4 py-2 border border-gray-300 rounded-lg">
185
+ <option value="electricity">Electricity</option>
186
+ <option value="gas">Gas</option>
187
+ <option value="water">Water</option>
188
+ </select>
189
+ </div>
190
+ <div>
191
+ <label for="editNotes" class="block text-sm font-medium text-gray-700 mb-1">Notes</label>
192
+ <textarea id="editNotes" rows="3" class="w-full px-4 py-2 border border-gray-300 rounded-lg"></textarea>
193
+ </div>
194
+ <div class="flex justify-end space-x-3">
195
+ <button type="button" id="deleteReading" class="px-4 py-2 bg-red-100 text-red-600 rounded-lg hover:bg-red-200">Delete</button>
196
+ <button type="submit" class="px-4 py-2 gradient-bg text-white rounded-lg hover:opacity-90">Save Changes</button>
197
+ </div>
198
+ </form>
199
+ </div>
200
+ </div>
201
+
202
+ <!-- Loading overlay -->
203
+ <div id="loadingOverlay" class="fixed inset-0 bg-black bg-opacity-30 flex items-center justify-center hidden">
204
+ <div class="bg-white p-8 rounded-xl text-center max-w-sm">
205
+ <div class="animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-blue-500 mx-auto mb-4"></div>
206
+ <h3 class="text-lg font-medium text-gray-800">Processing Data</h3>
207
+ <p class="text-gray-600 mt-2">Calculating projections and updating dashboard...</p>
208
+ </div>
209
+ </div>
210
+
211
+ <!-- Scripts -->
212
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
213
+ <script>
214
+ // Initialize date field with current date
215
+ document.addEventListener('DOMContentLoaded', function() {
216
+ const today = new Date();
217
+ const formattedDate = today.toISOString().substr(0, 10);
218
+ document.getElementById('readingDate').value = formattedDate;
219
+ });
220
+
221
+ // Mock database using localStorage
222
+ const db = {
223
+ readings: JSON.parse(localStorage.getItem('energyReadings')) || [],
224
+
225
+ save: function() {
226
+ localStorage.setItem('energyReadings', JSON.stringify(this.readings));
227
+ },
228
+
229
+ addReading: function(reading) {
230
+ reading.id = Date.now().toString();
231
+ this.readings.push(reading);
232
+ this.save();
233
+ return reading;
234
+ },
235
+
236
+ updateReading: function(id, updatedData) {
237
+ const index = this.readings.findIndex(r => r.id === id);
238
+ if (index !== -1) {
239
+ this.readings[index] = {...this.readings[index], ...updatedData};
240
+ this.save();
241
+ return true;
242
+ }
243
+ return false;
244
+ },
245
+
246
+ deleteReading: function(id) {
247
+ const index = this.readings.findIndex(r => r.id === id);
248
+ if (index !== -1) {
249
+ this.readings.splice(index, 1);
250
+ this.save();
251
+ return true;
252
+ }
253
+ return false;
254
+ },
255
+
256
+ getReadings: function() {
257
+ return [...this.readings].sort((a, b) => new Date(b.date) - new Date(a.date));
258
+ },
259
+
260
+ getReadingsByMonth: function(month, year) {
261
+ return this.readings.filter(r => {
262
+ const d = new Date(r.date);
263
+ return d.getMonth() === month && d.getFullYear() === year;
264
+ }).sort((a, b) => new Date(a.date) - new Date(b.date));
265
+ }
266
+ };
267
+
268
+ // DOM Elements
269
+ const readingForm = document.getElementById('readingForm');
270
+ const readingsTableBody = document.getElementById('readingsTableBody');
271
+ const editModal = document.getElementById('editModal');
272
+ const closeModal = document.getElementById('closeModal');
273
+ const editForm = document.getElementById('editForm');
274
+ const deleteReadingBtn = document.getElementById('deleteReading');
275
+ const loadingOverlay = document.getElementById('loadingOverlay');
276
+
277
+ // Initialize Chart
278
+ let consumptionChart;
279
+ function initChart() {
280
+ const ctx = document.getElementById('consumptionChart').getContext('2d');
281
+ consumptionChart = new Chart(ctx, {
282
+ type: 'line',
283
+ data: {
284
+ labels: [],
285
+ datasets: [{
286
+ label: 'Energy Consumption (kWh)',
287
+ data: [],
288
+ backgroundColor: 'rgba(54, 162, 235, 0.2)',
289
+ borderColor: 'rgba(54, 162, 235, 1)',
290
+ borderWidth: 2,
291
+ tension: 0.1
292
+ }]
293
+ },
294
+ options: {
295
+ responsive: true,
296
+ maintainAspectRatio: false,
297
+ scales: {
298
+ y: {
299
+ beginAtZero: true
300
+ }
301
+ }
302
+ }
303
+ });
304
+ }
305
+
306
+ // Format date for display
307
+ function formatDate(dateString) {
308
+ const options = { year: 'numeric', month: 'short', day: 'numeric' };
309
+ return new Date(dateString).toLocaleDateString(undefined, options);
310
+ }
311
+
312
+ // Calculate daily average
313
+ function calculateDailyAverage(reading, previousReading) {
314
+ if (!previousReading) return 0;
315
+
316
+ const date1 = new Date(previousReading.date);
317
+ const date2 = new Date(reading.date);
318
+ const diffTime = Math.abs(date2 - date1);
319
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
320
+
321
+ if (diffDays === 0) return 0;
322
+
323
+ return ((reading.value - previousReading.value) / diffDays).toFixed(2);
324
+ }
325
+
326
+ // Update dashboard metrics
327
+ function updateDashboard() {
328
+ const readings = db.getReadings();
329
+ if (readings.length === 0) return;
330
+
331
+ const currentDate = new Date();
332
+ const currentMonth = currentDate.getMonth();
333
+ const currentYear = currentDate.getFullYear();
334
+
335
+ // Get readings for current month
336
+ const monthReadings = db.getReadingsByMonth(currentMonth, currentYear);
337
+
338
+ if (monthReadings.length >= 2) {
339
+ const firstReading = monthReadings[0];
340
+ const lastReading = monthReadings[monthReadings.length - 1];
341
+
342
+ // Calculate days between first and last reading
343
+ const date1 = new Date(firstReading.date);
344
+ const date2 = new Date(lastReading.date);
345
+ const diffTime = Math.abs(date2 - date1);
346
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) || 1;
347
+
348
+ // Calculate total consumption and daily average
349
+ const totalConsumption = lastReading.value - firstReading.value;
350
+ const dailyAvg = (totalConsumption / diffDays).toFixed(2);
351
+
352
+ // Update metrics
353
+ document.getElementById('currentMonthUsage').textContent = `${totalConsumption.toFixed(2)} kWh`;
354
+ document.getElementById('avgDailyUsage').textContent = `${dailyAvg} kWh`;
355
+
356
+ // Projected monthly usage
357
+ const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
358
+ const projectedUsage = (dailyAvg * daysInMonth).toFixed(2);
359
+ document.getElementById('projectedUsage').textContent = `${projectedUsage} kWh`;
360
+ }
361
+ }
362
+
363
+ // Update chart data
364
+ function updateChart() {
365
+ const readings = db.getReadings();
366
+
367
+ if (readings.length >= 2) {
368
+ // Group readings by month and calculate monthly totals
369
+ const monthlyData = {};
370
+
371
+ readings.forEach(reading => {
372
+ const date = new Date(reading.date);
373
+ const monthYear = `${date.getFullYear()}-${date.getMonth()}`;
374
+
375
+ if (!monthlyData[monthYear]) {
376
+ monthlyData[monthYear] = {
377
+ date: new Date(date.getFullYear(), date.getMonth(), 1),
378
+ total: 0,
379
+ count: 0
380
+ };
381
+ }
382
+
383
+ monthlyData[monthYear].total += reading.value;
384
+ monthlyData[monthYear].count++;
385
+ });
386
+
387
+ // Calculate monthly averages
388
+ const chartLabels = [];
389
+ const chartData = [];
390
+
391
+ Object.keys(monthlyData).sort().forEach(key => {
392
+ const monthData = monthlyData[key];
393
+ const avg = monthData.total / monthData.count;
394
+
395
+ chartLabels.push(monthData.date.toLocaleDateString(undefined, { month: 'short', year: 'numeric' }));
396
+ chartData.push(avg);
397
+ });
398
+
399
+ // Update chart
400
+ if (consumptionChart) {
401
+ consumptionChart.data.labels = chartLabels;
402
+ consumptionChart.data.datasets[0].data = chartData;
403
+ consumptionChart.update();
404
+ }
405
+ }
406
+ }
407
+
408
+ // Render readings table
409
+ function renderReadingsTable() {
410
+ const readings = db.getReadings();
411
+
412
+ if (readings.length === 0) {
413
+ readingsTableBody.innerHTML = `
414
+ <tr>
415
+ <td colspan="5" class="px-6 py-4 text-center text-gray-500">No readings yet. Add your first reading!</td>
416
+ </tr>
417
+ `;
418
+ return;
419
+ }
420
+
421
+ let tableHTML = '';
422
+
423
+ for (let i = 0; i < readings.length; i++) {
424
+ const reading = readings[i];
425
+ const previousReading = i < readings.length - 1 ? readings[i + 1] : null;
426
+ const dailyAvg = calculateDailyAverage(reading, previousReading);
427
+
428
+ tableHTML += `
429
+ <tr class="hover:bg-gray-50">
430
+ <td class="px-6 py-4 whitespace-nowrap">${formatDate(reading.date)}</td>
431
+ <td class="px-6 py-4 whitespace-nowrap capitalize">${reading.type}</td>
432
+ <td class="px-6 py-4 whitespace-nowrap">${reading.value.toFixed(2)} kWh</td>
433
+ <td class="px-6 py-4 whitespace-nowrap">${dailyAvg} kWh/day</td>
434
+ <td class="px-6 py-4 whitespace-nowrap">
435
+ <button class="text-blue-600 hover:text-blue-800 mr-3 edit-btn" data-id="${reading.id}">
436
+ <i class="fas fa-edit"></i>
437
+ </button>
438
+ <button class="text-red-600 hover:text-red-800 delete-btn" data-id="${reading.id}">
439
+ <i class="fas fa-trash"></i>
440
+ </button>
441
+ </td>
442
+ </tr>
443
+ `;
444
+ }
445
+
446
+ readingsTableBody.innerHTML = tableHTML;
447
+
448
+ // Add event listeners to edit and delete buttons
449
+ document.querySelectorAll('.edit-btn').forEach(btn => {
450
+ btn.addEventListener('click', function() {
451
+ const id = this.getAttribute('data-id');
452
+ openEditModal(id);
453
+ });
454
+ });
455
+
456
+ document.querySelectorAll('.delete-btn').forEach(btn => {
457
+ btn.addEventListener('click', function() {
458
+ const id = this.getAttribute('data-id');
459
+ if (confirm('Are you sure you want to delete this reading?')) {
460
+ db.deleteReading(id);
461
+ renderReadingsTable();
462
+ updateDashboard();
463
+ updateChart();
464
+ }
465
+ });
466
+ });
467
+ }
468
+
469
+ // Open edit modal with reading data
470
+ function openEditModal(id) {
471
+ const reading = db.readings.find(r => r.id === id);
472
+ if (!reading) return;
473
+
474
+ document.getElementById('editId').value = reading.id;
475
+ document.getElementById('editDate').value = reading.date;
476
+ document.getElementById('editReading').value = reading.value;
477
+ document.getElementById('editType').value = reading.type;
478
+ document.getElementById('editNotes').value = reading.notes || '';
479
+
480
+ editModal.classList.remove('hidden');
481
+ }
482
+
483
+ // Close edit modal
484
+ function closeEditModal() {
485
+ editModal.classList.add('hidden');
486
+ }
487
+
488
+ // Initialize app
489
+ function initApp() {
490
+ initChart();
491
+ renderReadingsTable();
492
+ updateDashboard();
493
+ updateChart();
494
+
495
+ // Form submission for new reading
496
+ readingForm.addEventListener('submit', function(e) {
497
+ e.preventDefault();
498
+
499
+ const date = document.getElementById('readingDate').value;
500
+ const value = parseFloat(document.getElementById('meterReading').value);
501
+ const type = document.getElementById('meterType').value;
502
+ const notes = document.getElementById('notes').value;
503
+
504
+ if (!date || isNaN(value)) {
505
+ alert('Please enter a valid date and reading value');
506
+ return;
507
+ }
508
+
509
+ // Show loading overlay
510
+ loadingOverlay.classList.remove('hidden');
511
+
512
+ // Simulate processing delay
513
+ setTimeout(() => {
514
+ // Add new reading
515
+ db.addReading({
516
+ date,
517
+ value,
518
+ type,
519
+ notes
520
+ });
521
+
522
+ // Reset form (but keep current date)
523
+ document.getElementById('meterReading').value = '';
524
+ document.getElementById('notes').value = '';
525
+ document.getElementById('readingDate').value = new Date().toISOString().substr(0, 10);
526
+
527
+ // Update UI
528
+ renderReadingsTable();
529
+ updateDashboard();
530
+ updateChart();
531
+
532
+ // Hide loading overlay
533
+ loadingOverlay.classList.add('hidden');
534
+ }, 1000);
535
+ });
536
+
537
+ // Form submission for editing reading
538
+ editForm.addEventListener('submit', function(e) {
539
+ e.preventDefault();
540
+
541
+ const id = document.getElementById('editId').value;
542
+ const date = document.getElementById('editDate').value;
543
+ const value = parseFloat(document.getElementById('editReading').value);
544
+ const type = document.getElementById('editType').value;
545
+ const notes = document.getElementById('editNotes').value;
546
+
547
+ if (!date || isNaN(value)) {
548
+ alert('Please enter a valid date and reading value');
549
+ return;
550
+ }
551
+
552
+ db.updateReading(id, {
553
+ date,
554
+ value,
555
+ type,
556
+ notes
557
+ });
558
+
559
+ closeEditModal();
560
+ renderReadingsTable();
561
+ updateDashboard();
562
+ updateChart();
563
+ });
564
+
565
+ // Delete reading button
566
+ deleteReadingBtn.addEventListener('click', function() {
567
+ const id = document.getElementById('editId').value;
568
+
569
+ if (confirm('Are you sure you want to delete this reading?')) {
570
+ db.deleteReading(id);
571
+ closeEditModal();
572
+ renderReadingsTable();
573
+ updateDashboard();
574
+ updateChart();
575
+ }
576
+ });
577
+
578
+ // Close modal button
579
+ closeModal.addEventListener('click', closeEditModal);
580
+ }
581
+
582
+ // Start the app when DOM is loaded
583
+ document.addEventListener('DOMContentLoaded', initApp);
584
+ </script>
585
+ <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=aaronxavier/energytracker" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
586
+ </html>