offerpk3 commited on
Commit
8811a93
·
verified ·
1 Parent(s): f91a424

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +548 -19
index.html CHANGED
@@ -1,19 +1,548 @@
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>Network Device Monitoring Dashboard</title>
7
+ <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
10
+ </head>
11
+ <body class="bg-gray-50">
12
+ <!-- Header Section -->
13
+ <header class="bg-indigo-700 text-white shadow-lg">
14
+ <div class="container mx-auto px-4 py-6 flex justify-between items-center">
15
+ <div class="flex items-center space-x-3">
16
+ <i class="fas fa-network-wired text-3xl"></i>
17
+ <h1 class="text-2xl font-bold">Network Device Monitor</h1>
18
+ </div>
19
+ <div class="flex items-center space-x-4">
20
+ <div class="relative">
21
+ <i class="fas fa-bell text-xl"></i>
22
+ <span class="absolute top-0 right-0 bg-red-500 text-xs rounded-full h-4 w-4 flex items-center justify-center">3</span>
23
+ </div>
24
+ <div class="flex items-center space-x-2 bg-indigo-600 px-3 py-1 rounded-lg">
25
+ <i class="fas fa-user-circle"></i>
26
+ <span>Admin</span>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ </header>
31
+
32
+ <div class="container mx-auto px-4 py-8">
33
+ <!-- Dashboard Summary -->
34
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
35
+ <div class="bg-white rounded-xl shadow p-6 flex items-center">
36
+ <div class="bg-blue-100 p-4 rounded-xl mr-4">
37
+ <i class="fas fa-desktop text-blue-600 text-2xl"></i>
38
+ </div>
39
+ <div>
40
+ <p class="text-gray-500">Total Devices</p>
41
+ <p class="text-2xl font-bold" id="total-devices">0</p>
42
+ </div>
43
+ </div>
44
+ <div class="bg-white rounded-xl shadow p-6 flex items-center">
45
+ <div class="bg-green-100 p-4 rounded-xl mr-4">
46
+ <i class="fas fa-check-circle text-green-600 text-2xl"></i>
47
+ </div>
48
+ <div>
49
+ <p class="text-gray-500">Active Devices</p>
50
+ <p class="text-2xl font-bold" id="active-devices">0</p>
51
+ </div>
52
+ </div>
53
+ <div class="bg-white rounded-xl shadow p-6 flex items-center">
54
+ <div class="bg-red-100 p-4 rounded-xl mr-4">
55
+ <i class="fas fa-ban text-red-600 text-2xl"></i>
56
+ </div>
57
+ <div>
58
+ <p class="text-gray-500">Blocked Devices</p>
59
+ <p class="text-2xl font-bold" id="blocked-devices">0</p>
60
+ </div>
61
+ </div>
62
+ <div class="bg-white rounded-xl shadow p-6 flex items-center">
63
+ <div class="bg-purple-100 p-4 rounded-xl mr-4">
64
+ <i class="fas fa-rupee-sign text-purple-600 text-2xl"></i>
65
+ </div>
66
+ <div>
67
+ <p class="text-gray-500">Total Revenue</p>
68
+ <p class="text-2xl font-bold" id="total-revenue">₹0</p>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div class="flex flex-col lg:flex-row gap-8">
74
+ <!-- Left Column - Form and Stats -->
75
+ <div class="lg:w-1/3">
76
+ <!-- Add Device Form -->
77
+ <div class="bg-white rounded-xl shadow-lg p-6 mb-8">
78
+ <h2 class="text-xl font-bold mb-4 text-gray-800">Add New Device</h2>
79
+ <form id="device-form" class="space-y-4">
80
+ <div>
81
+ <label class="block text-gray-700 mb-2">MAC Address</label>
82
+ <input type="text" id="mac-address" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="AA:BB:CC:DD:EE:FF">
83
+ <p class="text-red-500 text-sm mt-1 hidden" id="mac-error">MAC address is required and must be unique</p>
84
+ </div>
85
+ <div>
86
+ <label class="block text-gray-700 mb-2">Device Name</label>
87
+ <input type="text" id="device-name" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="e.g. John's iPhone">
88
+ </div>
89
+ <div>
90
+ <label class="block text-gray-700 mb-2">User Name</label>
91
+ <input type="text" id="user-name" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="e.g. John Doe">
92
+ </div>
93
+ <div>
94
+ <label class="block text-gray-700 mb-2">Paid Amount (₹)</label>
95
+ <input type="number" id="paid-amount" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="e.g. 500">
96
+ <p class="text-red-500 text-sm mt-1 hidden" id="amount-error">Please enter a valid amount</p>
97
+ </div>
98
+ <button type="submit" class="w-full bg-indigo-600 text-white py-2 rounded-lg hover:bg-indigo-700 transition duration-300 flex items-center justify-center">
99
+ <i class="fas fa-plus-circle mr-2"></i> Add New Device
100
+ </button>
101
+ </form>
102
+ </div>
103
+
104
+ <!-- Payment Statistics -->
105
+ <div class="bg-white rounded-xl shadow-lg p-6">
106
+ <h2 class="text-xl font-bold mb-4 text-gray-800">Payment Statistics</h2>
107
+ <div class="mb-6">
108
+ <div class="flex justify-between mb-1">
109
+ <span>Total Revenue</span>
110
+ <span id="revenue-stat">₹0</span>
111
+ </div>
112
+ <div class="h-2 bg-gray-200 rounded-full">
113
+ <div class="h-2 bg-green-500 rounded-full" style="width: 0%" id="revenue-bar"></div>
114
+ </div>
115
+ </div>
116
+ <div class="mb-6">
117
+ <div class="flex justify-between mb-1">
118
+ <span>Avg. Payment</span>
119
+ <span id="avg-payment">₹0</span>
120
+ </div>
121
+ <div class="h-2 bg-gray-200 rounded-full">
122
+ <div class="h-2 bg-blue-500 rounded-full" style="width: 0%" id="avg-payment-bar"></div>
123
+ </div>
124
+ </div>
125
+ <div>
126
+ <div class="flex justify-between mb-1">
127
+ <span>Unpaid Devices</span>
128
+ <span id="unpaid-count">0</span>
129
+ </div>
130
+ <div class="h-2 bg-gray-200 rounded-full">
131
+ <div class="h-2 bg-red-500 rounded-full" style="width: 0%" id="unpaid-bar"></div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+
137
+ <!-- Right Column - Device Table -->
138
+ <div class="lg:w-2/3">
139
+ <div class="bg-white rounded-xl shadow-lg p-6">
140
+ <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6">
141
+ <h2 class="text-xl font-bold text-gray-800 mb-4 md:mb-0">Registered Devices</h2>
142
+ <div class="flex space-x-3 w-full md:w-auto">
143
+ <div class="relative w-full md:w-64">
144
+ <input type="text" id="search-input" class="w-full pl-10 pr-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="Search devices...">
145
+ <i class="fas fa-search absolute left-3 top-3 text-gray-400"></i>
146
+ </div>
147
+ <button id="export-btn" class="bg-green-600 text-white px-4 py-2 rounded-lg hover:bg-green-700 transition duration-300 flex items-center">
148
+ <i class="fas fa-file-export mr-2"></i> CSV
149
+ </button>
150
+ </div>
151
+ </div>
152
+
153
+ <div class="overflow-x-auto">
154
+ <table class="min-w-full divide-y divide-gray-200">
155
+ <thead>
156
+ <tr>
157
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">#</th>
158
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">MAC Address</th>
159
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Device Name</th>
160
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">User Name</th>
161
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Paid (₹)</th>
162
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Added Time</th>
163
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
164
+ <th class="px-4 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
165
+ </tr>
166
+ </thead>
167
+ <tbody id="device-table" class="bg-white divide-y divide-gray-200">
168
+ <!-- Device rows will be populated here -->
169
+ </tbody>
170
+ </table>
171
+ </div>
172
+
173
+ <div class="mt-6 flex flex-col sm:flex-row justify-between items-center border-t pt-4">
174
+ <div class="mb-4 sm:mb-0">
175
+ <p class="text-gray-600">Total Paid Amount: <span class="font-bold" id="total-paid">₹0</span></p>
176
+ </div>
177
+ <div class="flex space-x-2">
178
+ <button class="px-4 py-2 border rounded-lg hover:bg-gray-100">Previous</button>
179
+ <button class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">1</button>
180
+ <button class="px-4 py-2 border rounded-lg hover:bg-gray-100">Next</button>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+ </div>
187
+
188
+ <!-- Edit Device Modal -->
189
+ <div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
190
+ <div class="bg-white rounded-xl shadow-lg p-6 w-full max-w-md">
191
+ <div class="flex justify-between items-center mb-4">
192
+ <h3 class="text-xl font-bold text-gray-800">Edit Device</h3>
193
+ <button id="close-modal" class="text-gray-500 hover:text-gray-700">
194
+ <i class="fas fa-times"></i>
195
+ </button>
196
+ </div>
197
+ <form id="edit-form" class="space-y-4">
198
+ <input type="hidden" id="edit-id">
199
+ <div>
200
+ <label class="block text-gray-700 mb-2">MAC Address</label>
201
+ <input type="text" id="edit-mac" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" readonly>
202
+ </div>
203
+ <div>
204
+ <label class="block text-gray-700 mb-2">Device Name</label>
205
+ <input type="text" id="edit-device-name" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
206
+ </div>
207
+ <div>
208
+ <label class="block text-gray-700 mb-2">User Name</label>
209
+ <input type="text" id="edit-user-name" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
210
+ </div>
211
+ <div>
212
+ <label class="block text-gray-700 mb-2">Paid Amount (₹)</label>
213
+ <input type="number" id="edit-paid-amount" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500">
214
+ </div>
215
+ <div class="flex space-x-4 pt-2">
216
+ <button type="submit" class="flex-1 bg-indigo-600 text-white py-2 rounded-lg hover:bg-indigo-700 transition duration-300">Update</button>
217
+ <button type="button" id="cancel-edit" class="flex-1 bg-gray-300 text-gray-700 py-2 rounded-lg hover:bg-gray-400 transition duration-300">Cancel</button>
218
+ </div>
219
+ </form>
220
+ </div>
221
+ </div>
222
+
223
+ <script>
224
+ // Initialize device data from localStorage or empty array
225
+ let devices = JSON.parse(localStorage.getItem('networkDevices')) || [];
226
+ let editDeviceId = null;
227
+
228
+ // DOM elements
229
+ const deviceForm = document.getElementById('device-form');
230
+ const deviceTable = document.getElementById('device-table');
231
+ const editModal = document.getElementById('edit-modal');
232
+ const editForm = document.getElementById('edit-form');
233
+ const searchInput = document.getElementById('search-input');
234
+ const exportBtn = document.getElementById('export-btn');
235
+
236
+ // Initialize the app
237
+ document.addEventListener('DOMContentLoaded', () => {
238
+ renderDeviceTable();
239
+ updateSummary();
240
+ attachEventListeners();
241
+ });
242
+
243
+ // Event listeners
244
+ function attachEventListeners() {
245
+ deviceForm.addEventListener('submit', addNewDevice);
246
+ editForm.addEventListener('submit', updateDevice);
247
+ document.getElementById('close-modal').addEventListener('click', closeEditModal);
248
+ document.getElementById('cancel-edit').addEventListener('click', closeEditModal);
249
+ searchInput.addEventListener('input', filterDevices);
250
+ exportBtn.addEventListener('click', exportToCSV);
251
+ }
252
+
253
+ // Add new device
254
+ function addNewDevice(e) {
255
+ e.preventDefault();
256
+
257
+ const macAddress = document.getElementById('mac-address').value.trim();
258
+ const deviceName = document.getElementById('device-name').value.trim();
259
+ const userName = document.getElementById('user-name').value.trim();
260
+ const paidAmount = parseFloat(document.getElementById('paid-amount').value);
261
+
262
+ // Reset errors
263
+ document.getElementById('mac-error').classList.add('hidden');
264
+ document.getElementById('amount-error').classList.add('hidden');
265
+
266
+ let isValid = true;
267
+
268
+ // Validation
269
+ if (!macAddress || !isValidMAC(macAddress)) {
270
+ document.getElementById('mac-error').classList.remove('hidden');
271
+ isValid = false;
272
+ }
273
+
274
+ if (isDuplicateMAC(macAddress)) {
275
+ document.getElementById('mac-error').textContent = 'MAC address already exists';
276
+ document.getElementById('mac-error').classList.remove('hidden');
277
+ isValid = false;
278
+ }
279
+
280
+ if (!deviceName) {
281
+ isValid = false;
282
+ }
283
+
284
+ if (isNaN(paidAmount) {
285
+ document.getElementById('amount-error').classList.remove('hidden');
286
+ isValid = false;
287
+ }
288
+
289
+ if (!isValid) return;
290
+
291
+ // Create new device object
292
+ const newDevice = {
293
+ id: Date.now(),
294
+ mac: formatMAC(macAddress),
295
+ deviceName,
296
+ userName,
297
+ paidAmount,
298
+ addedTime: new Date().toLocaleString(),
299
+ status: 'Active'
300
+ };
301
+
302
+ // Add to devices array and update storage
303
+ devices.push(newDevice);
304
+ localStorage.setItem('networkDevices', JSON.stringify(devices));
305
+
306
+ // Reset form and update UI
307
+ deviceForm.reset();
308
+ renderDeviceTable();
309
+ updateSummary();
310
+
311
+ // Show success message
312
+ showNotification('Device added successfully!', 'success');
313
+ }
314
+
315
+ // Render device table
316
+ function renderDeviceTable(filteredDevices = null) {
317
+ const devicesToRender = filteredDevices || devices;
318
+ deviceTable.innerHTML = '';
319
+
320
+ if (devicesToRender.length === 0) {
321
+ deviceTable.innerHTML = `
322
+ <tr>
323
+ <td colspan="8" class="px-4 py-8 text-center text-gray-500">
324
+ <i class="fas fa-inbox text-4xl mb-2"></i>
325
+ <p>No devices found. Add a new device to get started.</p>
326
+ </td>
327
+ </tr>
328
+ `;
329
+ return;
330
+ }
331
+
332
+ devicesToRender.forEach((device, index) => {
333
+ const row = document.createElement('tr');
334
+ row.innerHTML = `
335
+ <td class="px-4 py-3 whitespace-nowrap">${index + 1}</td>
336
+ <td class="px-4 py-3 whitespace-nowrap font-mono">${device.mac}</td>
337
+ <td class="px-4 py-3">${device.deviceName}</td>
338
+ <td class="px-4 py-3">${device.userName}</td>
339
+ <td class="px-4 py-3 font-medium ${device.paidAmount > 0 ? 'text-green-600' : 'text-red-600'}">₹${device.paidAmount}</td>
340
+ <td class="px-4 py-3 whitespace-nowrap">${device.addedTime}</td>
341
+ <td class="px-4 py-3">
342
+ <span class="px-2 py-1 rounded-full text-xs font-medium ${device.status === 'Active' ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800'}">
343
+ ${device.status}
344
+ </span>
345
+ </td>
346
+ <td class="px-4 py-3 whitespace-nowrap">
347
+ <button class="text-blue-600 hover:text-blue-800 mr-2 edit-btn" data-id="${device.id}">
348
+ <i class="fas fa-edit"></i>
349
+ </button>
350
+ <button class="text-red-600 hover:text-red-800 mr-2 block-btn" data-id="${device.id}">
351
+ <i class="fas fa-ban"></i>
352
+ </button>
353
+ <button class="text-gray-600 hover:text-gray-800 delete-btn" data-id="${device.id}">
354
+ <i class="fas fa-trash"></i>
355
+ </button>
356
+ </td>
357
+ `;
358
+ deviceTable.appendChild(row);
359
+ });
360
+
361
+ // Attach event listeners to action buttons
362
+ document.querySelectorAll('.edit-btn').forEach(btn => {
363
+ btn.addEventListener('click', () => openEditModal(btn.dataset.id));
364
+ });
365
+
366
+ document.querySelectorAll('.block-btn').forEach(btn => {
367
+ btn.addEventListener('click', () => blockDevice(btn.dataset.id));
368
+ });
369
+
370
+ document.querySelectorAll('.delete-btn').forEach(btn => {
371
+ btn.addEventListener('click', () => deleteDevice(btn.dataset.id));
372
+ });
373
+ }
374
+
375
+ // Update summary stats
376
+ function updateSummary() {
377
+ const totalDevices = devices.length;
378
+ const activeDevices = devices.filter(d => d.status === 'Active').length;
379
+ const blockedDevices = devices.filter(d => d.status === 'Blocked').length;
380
+ const totalRevenue = devices.reduce((sum, device) => sum + device.paidAmount, 0);
381
+ const unpaidDevices = devices.filter(d => d.paidAmount <= 0).length;
382
+ const avgPayment = totalDevices > 0 ? totalRevenue / totalDevices : 0;
383
+
384
+ // Update dashboard cards
385
+ document.getElementById('total-devices').textContent = totalDevices;
386
+ document.getElementById('active-devices').textContent = activeDevices;
387
+ document.getElementById('blocked-devices').textContent = blockedDevices;
388
+ document.getElementById('total-revenue').textContent = `₹${totalRevenue.toFixed(2)}`;
389
+
390
+ // Update payment stats
391
+ document.getElementById('revenue-stat').textContent = `₹${totalRevenue.toFixed(2)}`;
392
+ document.getElementById('avg-payment').textContent = `₹${avgPayment.toFixed(2)}`;
393
+ document.getElementById('unpaid-count').textContent = unpaidDevices;
394
+ document.getElementById('total-paid').textContent = `₹${totalRevenue.toFixed(2)}`;
395
+
396
+ // Update progress bars
397
+ const maxRevenue = Math.max(1000, totalRevenue);
398
+ document.getElementById('revenue-bar').style.width = `${(totalRevenue / maxRevenue) * 100}%`;
399
+ document.getElementById('avg-payment-bar').style.width = `${(avgPayment / 500) * 100}%`;
400
+ document.getElementById('unpaid-bar').style.width = `${(unpaidDevices / totalDevices) * 100 || 0}%`;
401
+ }
402
+
403
+ // Open edit modal
404
+ function openEditModal(deviceId) {
405
+ const device = devices.find(d => d.id == deviceId);
406
+ if (!device) return;
407
+
408
+ document.getElementById('edit-id').value = device.id;
409
+ document.getElementById('edit-mac').value = device.mac;
410
+ document.getElementById('edit-device-name').value = device.deviceName;
411
+ document.getElementById('edit-user-name').value = device.userName;
412
+ document.getElementById('edit-paid-amount').value = device.paidAmount;
413
+
414
+ editModal.classList.remove('hidden');
415
+ }
416
+
417
+ // Close edit modal
418
+ function closeEditModal() {
419
+ editModal.classList.add('hidden');
420
+ }
421
+
422
+ // Update device
423
+ function updateDevice(e) {
424
+ e.preventDefault();
425
+
426
+ const deviceId = document.getElementById('edit-id').value;
427
+ const device = devices.find(d => d.id == deviceId);
428
+ if (!device) return;
429
+
430
+ device.deviceName = document.getElementById('edit-device-name').value.trim();
431
+ device.userName = document.getElementById('edit-user-name').value.trim();
432
+ device.paidAmount = parseFloat(document.getElementById('edit-paid-amount').value);
433
+
434
+ // Update storage and UI
435
+ localStorage.setItem('networkDevices', JSON.stringify(devices));
436
+ renderDeviceTable();
437
+ updateSummary();
438
+ closeEditModal();
439
+
440
+ // Show success message
441
+ showNotification('Device updated successfully!', 'success');
442
+ }
443
+
444
+ // Block device
445
+ function blockDevice(deviceId) {
446
+ const device = devices.find(d => d.id == deviceId);
447
+ if (!device) return;
448
+
449
+ device.status = device.status === 'Active' ? 'Blocked' : 'Active';
450
+
451
+ // Update storage and UI
452
+ localStorage.setItem('networkDevices', JSON.stringify(devices));
453
+ renderDeviceTable();
454
+ updateSummary();
455
+
456
+ // Show notification
457
+ const action = device.status === 'Blocked' ? 'blocked' : 'unblocked';
458
+ showNotification(`Device has been ${action}`, 'info');
459
+
460
+ // Show alert as requested
461
+ alert(`Device with MAC ${device.mac} has been ${action}`);
462
+ }
463
+
464
+ // Delete device
465
+ function deleteDevice(deviceId) {
466
+ if (!confirm('Are you sure you want to delete this device?')) return;
467
+
468
+ devices = devices.filter(d => d.id != deviceId);
469
+
470
+ // Update storage and UI
471
+ localStorage.setItem('networkDevices', JSON.stringify(devices));
472
+ renderDeviceTable();
473
+ updateSummary();
474
+
475
+ // Show success message
476
+ showNotification('Device deleted successfully!', 'success');
477
+ }
478
+
479
+ // Filter devices
480
+ function filterDevices() {
481
+ const searchTerm = searchInput.value.toLowerCase();
482
+
483
+ if (!searchTerm) {
484
+ renderDeviceTable();
485
+ return;
486
+ }
487
+
488
+ const filtered = devices.filter(device =>
489
+ device.mac.toLowerCase().includes(searchTerm) ||
490
+ device.deviceName.toLowerCase().includes(searchTerm) ||
491
+ device.userName.toLowerCase().includes(searchTerm)
492
+ );
493
+
494
+ renderDeviceTable(filtered);
495
+ }
496
+
497
+ // Export to CSV
498
+ function exportToCSV() {
499
+ if (devices.length === 0) {
500
+ showNotification('No devices to export', 'warning');
501
+ return;
502
+ }
503
+
504
+ // Create CSV header
505
+ let csvContent = "MAC Address,Device Name,User Name,Paid Amount,Status,Added Time\n";
506
+
507
+ // Add each device as a row
508
+ devices.forEach(device => {
509
+ csvContent += `"${device.mac}","${device.deviceName}","${device.userName}",${device.paidAmount},"${device.status}","${device.addedTime}"\n`;
510
+ });
511
+
512
+ // Create download link
513
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
514
+ const url = URL.createObjectURL(blob);
515
+ const link = document.createElement('a');
516
+ link.setAttribute('href', url);
517
+ link.setAttribute('download', 'network-devices.csv');
518
+ link.style.visibility = 'hidden';
519
+ document.body.appendChild(link);
520
+ link.click();
521
+ document.body.removeChild(link);
522
+
523
+ showNotification('CSV exported successfully!', 'success');
524
+ }
525
+
526
+ // Helper functions
527
+ function isValidMAC(mac) {
528
+ // Simple MAC validation
529
+ return /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(mac);
530
+ }
531
+
532
+ function formatMAC(mac) {
533
+ // Format MAC address consistently
534
+ return mac.replace(/-/g, ':').toUpperCase();
535
+ }
536
+
537
+ function isDuplicateMAC(mac) {
538
+ const formattedMAC = formatMAC(mac);
539
+ return devices.some(d => d.mac === formattedMAC);
540
+ }
541
+
542
+ function showNotification(message, type) {
543
+ // In a real app, this would show a toast notification
544
+ alert(`${type.toUpperCase()}: ${message}`);
545
+ }
546
+ </script>
547
+ </body>
548
+ </html>