anycoder-0ceb77c8 / index.html
tomzarai's picture
Upload folder using huggingface_hub
57bbd8b verified
Raw History Blame Contribute Delete
44.1 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Device Manager | Apple Style</title> <!-- Import Google Fonts (San Francisco style approximation) --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <!-- Font Awesome for Icons --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> :root { --primary-color: #007AFF; --primary-hover: #0056b3; --danger-color: #FF3B30; --danger-hover: #d63226; --success-color: #34C759; --bg-color: #F5F5F7; --card-bg: #FFFFFF; --text-main: #1D1D1F; --text-secondary: #8E8E93; --border-color: #D2D2D7; --shadow: 0 4px 12px rgba(0, 0, 0, 0.08); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } [data-theme="dark"] { --bg-color: #000000; --card-bg: #1D1D1D; --text-main: #F5F5F7; --text-secondary: #8E8E93; --border-color: #38383A; --shadow: 0 4px 12px rgba(0, 0, 0, 0.4); } * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; background-color: var(--bg-color); color: var(--text-main); line-height: 1.5; transition: var(--transition); padding: 20px; } /* Header Section */ header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px; flex-wrap: wrap; gap: 20px; } .brand { display: flex; align-items: center; gap: 12px; } .brand-icon { width: 40px; height: 40px; background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white; font-size: 20px; } h1 { font-size: 28px; font-weight: 700; letter-spacing: -0.5px; } .brand-subtitle { font-size: 14px; color: var(--text-secondary); font-weight: 400; } .controls { display: flex; gap: 15px; align-items: center; } .theme-toggle { background: none; border: none; color: var(--text-main); font-size: 20px; cursor: pointer; padding: 8px; border-radius: 50%; transition: background 0.2s; } .theme-toggle:hover { background-color: rgba(128,128,128,0.2); } /* Stats Cards */ .stats-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 40px; } .stat-card { background-color: var(--card-bg); padding: 24px; border-radius: 16px; box-shadow: var(--shadow); display: flex; flex-direction: column; justify-content: space-between; transition: var(--transition); } .stat-card:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0,0,0,0.12); } .stat-label { font-size: 14px; color: var(--text-secondary); font-weight: 500; } .stat-value { font-size: 36px; font-weight: 700; margin: 8px 0 16px 0; color: var(--primary-color); } .stat-trend { font-size: 13px; color: var(--success-color); display: flex; align-items: center; gap: 5px; } /* Main Content Layout */ .main-container { display: grid; grid-template-columns: 350px 1fr; gap: 30px; } @media (max-width: 900px) { .main-container { grid-template-columns: 1fr; } } /* Sidebar / Add Device Form */ .sidebar-panel { background-color: var(--card-bg); padding: 30px; border-radius: 20px; box-shadow: var(--shadow); height: fit-content; } .panel-header { font-size: 20px; font-weight: 600; margin-bottom: 24px; padding-bottom: 16px; border-bottom: 1px solid var(--border-color); } .form-group { margin-bottom: 20px; } label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary); } input, select, textarea { width: 100%; padding: 12px; border-radius: 10px; border: 1px solid var(--border-color); background-color: var(--bg-color); color: var(--text-main); font-family: inherit; font-size: 14px; transition: var(--transition); outline: none; } input:focus, select:focus, textarea:focus { border-color: var(--primary-color); box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.2); } .btn { width: 100%; padding: 14px; border: none; border-radius: 12px; font-size: 15px; font-weight: 600; cursor: pointer; transition: var(--transition); display: flex; align-items: center; justify-content: center; gap: 8px; } .btn-primary { background-color: var(--primary-color); color: white; box-shadow: 0 4px 8px rgba(0, 122, 255, 0.3); } .btn-primary:hover { background-color: var(--primary-hover); transform: translateY(-1px); } .btn-secondary { background-color: var(--bg-color); color: var(--text-main); border: 1px solid var(--border-color); margin-top: 10px; } .btn-secondary:hover { background-color: var(--border-color); } /* Device List */ .device-list-container { background-color: var(--card-bg); border-radius: 20px; box-shadow: var(--shadow); overflow: hidden; display: flex; flex-direction: column; } .list-header { padding: 24px; border-bottom: 1px solid var(--border-color); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px; } .search-box { position: relative; width: 100%; max-width: 300px; } .search-box i { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-secondary); } .search-box input { padding-left: 40px; } .table-responsive { overflow-x: auto; } table { width: 100%; border-collapse: collapse; } th { background-color: var(--bg-color); text-align: left; padding: 16px 24px; font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; } td { padding: 18px 24px; border-bottom: 1px solid var(--border-color); font-size: 14px; color: var(--text-main); } tr:hover { background-color: rgba(0,0,0,0.02); } [data-theme="dark"] tr:hover { background-color: rgba(255,255,255,0.05); } .status-badge { display: inline-block; padding: 4px 10px; border-radius: 20px; font-size: 11px; font-weight: 600; text-transform: uppercase; } .status-active { background-color: rgba(52, 199, 89, 0.2); color: var(--success-color); } .status-pending { background-color: rgba(255, 165, 0, 0.2); color: #FF9500; } .status-offline { background-color: rgba(255, 59, 48, 0.2); color: var(--danger-color); } .device-name { font-weight: 600; display: flex; align-items: center; gap: 10px; } .device-icon { width: 32px; height: 32px; background: rgba(0,0,0,0.05); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: var(--primary-color); } [data-theme="dark"] .device-icon { background: rgba(255,255,255,0.1); } .action-group { display: flex; gap: 8px; } .action-btn { width: 32px; height: 32px; border-radius: 8px; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.2s; font-size: 14px; } .btn-edit { background-color: rgba(0, 122, 255, 0.1); color: var(--primary-color); } .btn-edit:hover { background-color: var(--primary-color); color: white; } .btn-delete { background-color: rgba(255, 59, 48, 0.1); color: var(--danger-color); } .btn-delete:hover { background-color: var(--danger-color); color: white; } /* Modal Styles */ .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(5px); z-index: 1000; display: none; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease; } .modal-overlay.active { display: flex; opacity: 1; } .modal { background-color: var(--card-bg); padding: 30px; border-radius: 24px; width: 90%; max-width: 500px; box-shadow: 0 20px 40px rgba(0,0,0,0.3); transform: scale(0.9); transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); } .modal-overlay.active .modal { transform: scale(1); } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .close-modal { background: none; border: none; font-size: 24px; cursor: pointer; color: var(--text-secondary); } /* Toast Notification */ .toast { position: fixed; bottom: 30px; right: 30px; background-color: var(--card-bg); padding: 16px 24px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); display: flex; align-items: center; gap: 12px; transform: translateY(100px); transition: transform 0.4s cubic-bezier(0.68, -0.55, 0.27, 1.55); z-index: 2000; border-left: 4px solid var(--primary-color); } .toast.show { transform: translateY(0); } .toast.success { border-left-color: var(--success-color); } .toast.error { border-left-color: var(--danger-color); } /* Built with Link */ .attribution { margin-top: 50px; text-align: center; font-size: 12px; } .attribution a { color: var(--text-secondary); text-decoration: none; transition: color 0.2s; } .attribution a:hover { color: var(--primary-color); text-decoration: underline; } </style> </head> <body> <!-- Header --> <header> <div class="brand"> <div class="brand-icon"> <i class="fa-solid fa-device-robot"></i> </div> <div> <h1>Device Manager</h1> <span class="brand-subtitle">Apple Ecosystem Management System</span> </div> </div> <div class="controls"> <button class="theme-toggle" id="themeToggle" title="Toggle Dark Mode"> <i class="fa-solid fa-moon"></i> </button> <button class="btn btn-primary" style="width: auto; padding: 10px 24px;" onclick="openModal()"> <i class="fa-solid fa-plus"></i> Add Device </button> </div> </header> <!-- Statistics --> <section class="stats-container"> <div class="stat-card"> <span class="stat-label">Total Devices</span> <div class="stat-value" id="totalDevices">0</div> <span class="stat-trend"><i class="fa-solid fa-circle-chevron-up"></i> +2 this week</span> </div> <div class="stat-card"> <span class="stat-label">Active Devices</span> <div class="stat-value" id="activeDevices" style="color: var(--success-color)">0</div> <span class="stat-trend"><i class="fa-solid fa-check-double"></i> System Online</span> </div> <div class="stat-card"> <span class="stat-label">Storage Used</span> <div class="stat-value" id="totalStorage">0 TB</div> <span class="stat-trend" style="color: var(--primary-color)"><i class="fa-solid fa-hard-drive"></i> Calculating...</span> </div> </section> <div class="main-container"> <!-- Sidebar Form --> <aside class="sidebar-panel"> <div class="panel-header"> <i class="fa-solid fa-circle-plus" style="color: var(--primary-color); margin-right: 8px;"></i> Register New Device </div> <form id="deviceForm"> <input type="hidden" id="deviceId"> <div class="form-group"> <label for="deviceName">Device Name</label> <input type="text" id="deviceName" placeholder="e.g., John's iPhone 15 Pro" required> </div> <div class="form-group"> <label for="deviceType">Product Type</label> <select id="deviceType" required> <option value="" disabled selected>Select a product</option> <optgroup label="iPhone"> <option value="iPhone 15 Pro Max">iPhone 15 Pro Max</option> <option value="iPhone 15 Pro">iPhone 15 Pro</option> <option value="iPhone 15 Plus">iPhone 15 Plus</option> <option value="iPhone 15">iPhone 15</option> <option value="iPhone 14 Pro Max">iPhone 14 Pro Max</option> <option value="iPhone 14">iPhone 14</option> <option value="iPhone SE (2022)">iPhone SE (2022)</option> </optgroup> <optgroup label="iPad"> <option value="iPad Pro 12.9">iPad Pro 12.9 (M2)</option> <option value="iPad Pro 11">iPad Pro 11 (M2)</option> <option value="iPad Air 10.9">iPad Air 10.9 (M2)</option> <option value="iPad (10th Gen)">iPad (10th Generation)</option> <option value="iPad Mini (6th Gen)">iPad Mini (6th Generation)</option> </optgroup> <optgroup label="Mac"> <option value="MacBook Pro 14">MacBook Pro 14 (M3)</option> <option value="MacBook Pro 16">MacBook Pro 16 (M3 Max)</option> <option value="MacBook Air 15">MacBook Air 15 (M2)</option> <option value="MacBook Air 13">MacBook Air 13 (M2)</option> <option value="iMac 24">iMac 24 (M3)</option> <option value="Mac mini (M2)">Mac mini (M2)</option> <option value="Mac Studio">Mac Studio (M2 Max)</option> <option value="Mac Pro">Mac Pro (M2 Ultra)</option> </optgroup> <optgroup label="Watch"> <option value="Apple Watch Ultra 2">Apple Watch Ultra 2</option> <option value="Apple Watch Series 9">Apple Watch Series 9</option> <option value="Apple Watch SE (2nd Gen)">Apple Watch SE (2nd Gen)</option> </optgroup> <optgroup label="Audio"> <option value="AirPods Pro 2">AirPods Pro 2 (USB-C)</option> <option value="AirPods Max">AirPods Max</option> <option value="AirPods 3">AirPods 3</option> </optgroup> </select> </div> <div class="form-group"> <label for="serialNumber">Serial Number</label> <input type="text" id="serialNumber" placeholder="e.g., F2X3L4567890" required pattern="[A-Za-z0-9]+"> </div> <div class="form-group"> <label for="ownerName">Owner / User</label> <input type="text" id="ownerName" placeholder="e.g., John Doe" required> </div> <div class="form-group"> <label for="purchaseDate">Purchase Date</label> <input type="date" id="purchaseDate" required> </div> <div class="form-group"> <label for="status">Device Status</label> <select id="status"> <option value="Active">Active (In Use)</option> <option value="Pending">Pending (Setup)</option> <option value="Offline">Offline (Repair)</option> <option value="Archived">Archived</option> </select> </div> <div class="form-group"> <label for="notes">Notes</label> <textarea id="notes" rows="3" placeholder="Any specific details..."></textarea> </div> <button type="submit" class="btn btn-primary" id="submitBtn"> <i class="fa-solid fa-floppy-disk"></i> Save Device </button> <button type="button" class="btn btn-secondary" id="cancelBtn" style="display: none;">Cancel Edit</button> </form> </aside> <!-- Device List --> <main class="device-list-container"> <div class="list-header"> <h2 style="font-size: 20px;">Registered Devices</h2> <div class="search-box"> <i class="fa-solid fa-magnifying-glass"></i> <input type="text" id="searchInput" placeholder="Search devices, serials, or owners..."> </div> </div> <div class="table-responsive"> <table> <thead> <tr> <th>Device</th> <th>Owner</th> <th>Serial Number</th> <th>Purchase Date</th> <th>Status</th> <th>Actions</th> </tr> </thead> <tbody id="deviceTableBody"> <!-- Rows will be populated by JS --> <tr> <td colspan="6" style="text-align: center; padding: 40px; color: var(--text-secondary);"> <i class="fa-solid fa-table-list" style="font-size: 32px; margin-bottom: 10px; display: block;"></i> No devices registered yet. Click "Add Device" to get started. </td> </tr> </tbody> </table> </div> </main> </div> <div class="attribution"> Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a> </div> <!-- Edit/View Modal --> <div class="modal-overlay" id="detailModal"> <div class="modal"> <div class="modal-header"> <h2 id="modalTitle" style="font-size: 22px; font-weight: 600;">Device Details</h2> <button class="close-modal" onclick="closeModal()">&times;</button> </div> <div id="modalContent"> <!-- Dynamic Content Here --> </div> <div style="display: flex; justify-content: flex-end; gap: 10px; margin-top: 30px;"> <button class="btn btn-secondary" onclick="closeModal()">Close</button> <button class="btn btn-primary" onclick="editCurrentDevice()"> <i class="fa-solid fa-pen-to-square"></i> Edit Device </button> </div> </div> </div> <!-- Toast Notification --> <div class="toast" id="toast"> <i class="fa-solid fa-circle-check" style="font-size: 24px;"></i> <span id="toastMessage">Action Successful</span> </div> <script> // --- Data Management --- let devices = [ { id: '1', name: 'Sarah\'s iPhone 15 Pro', type: 'iPhone 15 Pro', serial: 'F8X2K912345', owner: 'Sarah Jenkins', purchaseDate: '2023-10-15', status: 'Active', notes: 'Silver finish, insurance included.' }, { id: '2', name: 'Work MacBook Air', type: 'MacBook Air 15 (M2)', serial: 'C8D4M567890', owner: 'Company Asset', purchaseDate: '2023-02-10', status: 'Active', notes: 'Company managed device.' }, { id: '3', name: 'Home iPad Pro', type: 'iPad Pro 12.9', serial: 'G9H3N123456', owner: 'Michael Ross', purchaseDate: '2022-07-20', status: 'Offline', notes: 'Needs screen replacement.' } ]; // --- DOM Elements --- const deviceForm = document.getElementById('deviceForm'); const tableBody = document.getElementById('deviceTableBody'); const searchInput = document.getElementById('searchInput'); const themeToggle = document.getElementById('themeToggle'); const modal = document.getElementById('detailModal'); const modalContent = document.getElementById('modalContent'); const submitBtn = document.getElementById('submitBtn'); const cancelBtn = document.getElementById('cancelBtn'); const toast = document.getElementById('toast'); // --- Initialization --- document.addEventListener('DOMContentLoaded', () => { renderDevices(devices); updateStats(); // Check system preference for theme if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { document.body.setAttribute('data-theme', 'dark'); updateThemeIcon(); } }); // --- Core Functions --- function renderDevices(deviceList) { tableBody.innerHTML = ''; if (deviceList.length === 0) { tableBody.innerHTML = ` <tr> <td colspan="6" style="text-align: center; padding: 40px; color: var(--text-secondary);"> <i class="fa-solid fa-table-list" style="font-size: 32px; margin-bottom: 10px; display: block;"></i> No devices found matching your criteria. </td> </tr>`; return; } deviceList.forEach(device => { const tr = document.createElement('tr'); // Determine Icon based on type let iconClass = 'fa-mobile'; if (device.type.includes('iPhone')) iconClass = 'fa-mobile'; else if (device.type.includes('iPad')) iconClass = 'fa-tablet'; else if (device.type.includes('Mac')) iconClass = 'fa-laptop'; else if (device.type.includes('Watch')) iconClass = 'fa-watch'; else if (device.type.includes('AirPods')) iconClass = 'fa-headphones'; // Status Badge Logic let statusClass = ''; if (device.status === 'Active') statusClass = 'status-active'; else if (device.status === 'Pending') statusClass = 'status-pending'; else if (device.status === 'Offline') statusClass = 'status-offline'; else statusClass = 'status-offline'; // Default for archived tr.innerHTML = ` <td> <div class="device-name"> <div class="device-icon"> <i class="fa-solid ${iconClass}"></i> </div> <div> <div style="font-weight: 600;">${device.name}</div> <div style="font-size: 12px; color: var(--text-secondary);">${device.type}</div> </div> </div> </td> <td style="font-weight: 500;">${device.owner}</td> <td style="font-family: monospace; font-size: 13px; color: var(--text-secondary);">${device.serial}</td> <td>${device.purchaseDate}</td> <td><span class="status-badge ${statusClass}">${device.status}</span></td> <td> <div class="action-group"> <button class="action-btn btn-edit" title="View Details" onclick="viewDevice('${device.id}')"> <i class="fa-solid fa-eye"></i> </button> <button class="action-btn btn-edit" title="Edit" onclick="editDevice('${device.id}')"> <i class="fa-solid fa-pen-to-square"></i> </button> <button class="action-btn btn-delete" title="Delete" onclick="deleteDevice('${device.id}')"> <i class="fa-solid fa-trash"></i> </button> </div> </td> `; tableBody.appendChild(tr); }); updateStats(); } function updateStats() { const total = devices.length; const active = devices.filter(d => d.status === 'Active').length; document.getElementById('totalDevices').innerText = total; document.getElementById('activeDevices').innerText = active; // Simple estimation for storage (Mock logic) let totalStorage = 0; devices.forEach(d => { if(d.type.includes('iPhone') || d.type.includes('iPad')) totalStorage += 256; // assume 256GB avg else if(d.type.includes('Mac')) totalStorage += 1000; // assume 1TB avg else totalStorage += 64; // assume 64GB avg }); const tb = (totalStorage / 1024).toFixed(1); document.getElementById('totalStorage').innerText = `${tb} TB`; } function searchDevices(e) { const term = e.target.value.toLowerCase(); const filtered = devices.filter(device => device.name.toLowerCase().includes(term) || device.owner.toLowerCase().includes(term) || device.serial.toLowerCase().includes(term) || device.type.toLowerCase().includes(term) ); renderDevices(filtered); } // --- Form Handling --- deviceForm.addEventListener('submit', (e) => { e.preventDefault(); const deviceId = document.getElementById('deviceId').value; const name = document.getElementById('deviceName').value; const type = document.getElementById('deviceType').value; const serial = document.getElementById('serialNumber').value.toUpperCase(); const owner = document.getElementById('ownerName').value; const purchaseDate = document.getElementById('purchaseDate').value; const status = document.getElementById('status').value; const notes = document.getElementById('notes').value; if (deviceId) { // Edit existing const index = devices.findIndex(d => d.id === deviceId); if (index !== -1) { devices[index] = { id: deviceId, name, type, serial, owner, purchaseDate, status, notes }; showToast('Device updated successfully!', 'success'); } resetForm(); } else { // Add new const newDevice = { id: Date.now().toString(), name, type, serial, owner, purchaseDate, status, notes }; devices.unshift(newDevice); // Add to top showToast('New device added to inventory!', 'success'); resetForm(); } renderDevices(devices); }); function resetForm() { deviceForm.reset(); document.getElementById('deviceId').value = ''; submitBtn.innerHTML = '<i class="fa-solid fa-floppy-disk"></i> Save Device'; cancelBtn.style.display = 'none'; document.querySelector('.panel-header').innerHTML = '<i class="fa-solid fa-circle-plus" style="color: var(--primary-color); margin-right: 8px;"></i> Register New Device'; } function editDevice(id) { const device = devices.find(d => d.id === id); if (!device) return; document.getElementById('deviceId').value = device.id; document.getElementById('deviceName').value = device.name; document.getElementById('deviceType').value = device.type; document.getElementById('serialNumber').value = device.serial; document.getElementById('ownerName').value = device.owner; document.getElementById('purchaseDate').value = device.purchaseDate; document.getElementById('status').value = device.status; document.getElementById('notes').value = device.notes || ''; // Update UI for Edit mode submitBtn.innerHTML = '<i class="fa-solid fa-check"></i> Update Device'; cancelBtn.style.display = 'block'; document.querySelector('.panel-header').innerHTML = `<i class="fa-solid fa-pen-to-square" style="color: var(--primary-color); margin-right: 8px;"></i> Edit ${device.name}`; window.scrollTo({ top: 0, behavior: 'smooth' }); } function deleteDevice(id) { if (confirm('Are you sure you want to remove this device from management? This action cannot be undone.')) { devices = devices.filter(d => d.id !== id); renderDevices(devices); showToast('Device removed from system.', 'success'); updateStats(); } } // --- Modal Functions --- function viewDevice(id) { const device = devices.find(d => d.id === id); if (!device) return; let iconClass = 'fa-mobile'; if (device.type.includes('iPhone')) iconClass = 'fa-mobile'; else if (device.type.includes('iPad')) iconClass = 'fa-tablet'; else if (device.type.includes('Mac')) iconClass = 'fa-laptop'; else if (device.type.includes('Watch')) iconClass = 'fa-watch'; modalContent.innerHTML = ` <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid var(--border-color);"> <div style="font-size: 60px; color: var(--primary-color);"> <i class="fa-solid ${iconClass}"></i> </div> <div> <h3 style="font-size: 24px; font-weight: 700;">${device.name}</h3> <p style="color: var(--text-secondary); font-size: 16px;">${device.type}</p> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div class="form-group"> <label>Serial Number</label> <div style="font-family: monospace; font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${device.serial} </div> </div> <div class="form-group"> <label>Owner</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${device.owner} </div> </div> <div class="form-group"> <label>Purchase Date</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${formatDate(device.purchaseDate)} </div> </div> <div class="form-group"> <label>Management Status</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> <span class="status-badge ${getStatusClass(device.status)}">${device.status}</span> </div> </div> </div> <div class="form-group"> <label>Notes</label> <div style="font-size: 14px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color); color: var(--text-secondary);"> ${device.notes || 'No notes available.'} </div> </div> `; modal.classList.add('active'); } function editCurrentDevice() { // Get ID from the modal content (stored in a data attribute or logic) // Since we don't store ID in modal DOM, we find it by matching content or passing it better. // Let's fix the viewDevice function to pass ID or store it. // For this simple implementation, we'll just grab the first device that matches the name and serial (risky but works for demo) // Better approach: Add ID to modalContent.innerHTML as a hidden field or attribute // Let's re-implement viewDevice to store ID globally temporarily const device = devices.find(d => modalContent.innerText.includes(d.serial) && modalContent.innerText.includes(d.name) ); if(device) { closeModal(); editDevice(device.id); } } // Fix for editCurrentDevice to work reliably let currentModalDeviceId = null; function viewDevice(id) { currentModalDeviceId = id; const device = devices.find(d => d.id === id); if (!device) return; let iconClass = 'fa-mobile'; if (device.type.includes('iPhone')) iconClass = 'fa-mobile'; else if (device.type.includes('iPad')) iconClass = 'fa-tablet'; else if (device.type.includes('Mac')) iconClass = 'fa-laptop'; else if (device.type.includes('Watch')) iconClass = 'fa-watch'; modalContent.innerHTML = ` <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid var(--border-color);"> <div style="font-size: 60px; color: var(--primary-color);"> <i class="fa-solid ${iconClass}"></i> </div> <div> <h3 style="font-size: 24px; font-weight: 700;">${device.name}</h3> <p style="color: var(--text-secondary); font-size: 16px;">${device.type}</p> </div> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div class="form-group"> <label>Serial Number</label> <div style="font-family: monospace; font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${device.serial} </div> </div> <div class="form-group"> <label>Owner</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${device.owner} </div> </div> <div class="form-group"> <label>Purchase Date</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> ${formatDate(device.purchaseDate)} </div> </div> <div class="form-group"> <label>Management Status</label> <div style="font-size: 16px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color);"> <span class="status-badge ${getStatusClass(device.status)}">${device.status}</span> </div> </div> </div> <div class="form-group"> <label>Notes</label> <div style="font-size: 14px; padding: 10px; background: var(--bg-color); border-radius: 8px; border: 1px solid var(--border-color); color: var(--text-secondary);"> ${device.notes || 'No notes available.'} </div> </div> `; modal.classList.add('active'); } function editCurrentDevice() { if (currentModalDeviceId) { closeModal(); editDevice(currentModalDeviceId); } } function closeModal() { modal.classList.remove('active'); currentModalDeviceId = null; } // --- Utilities --- function showToast(message, type) { const toastMsg = document.getElementById('toastMessage'); toastMsg.innerText = message; toast.className = 'toast show ' + type; if (type === 'success') { document.getElementById('toast').innerHTML = '<i class="fa-solid fa-circle-check"></i> <span id="toastMessage">' + message + '</span>'; } else { document.getElementById('toast').innerHTML = '<i class="fa-solid fa-circle-exclamation"></i> <span id="toastMessage">' + message + '</span>'; } setTimeout(() => { toast.classList.remove('show'); }, 3000); } function updateThemeIcon() { const isDark = document.body.getAttribute('data-theme') === 'dark'; const icon = themeToggle.querySelector('i'); if (isDark) { icon.className = 'fa-solid fa-sun'; } else { icon.className = 'fa-solid fa-moon'; } } themeToggle.addEventListener('click', () => { if (document.body.getAttribute('data-theme') === 'dark') { document.body.removeAttribute('data-theme'); } else { document.body.setAttribute('data-theme', 'dark'); } updateThemeIcon(); }); function getStatusClass(status) { if (status === 'Active') return 'status-active'; if (status === 'Pending') return 'status-pending'; if (status === 'Offline') return 'status-offline'; return 'status-offline'; } function formatDate(dateString) { const options = { year: 'numeric', month: 'short', day: 'numeric' }; return new Date(dateString).toLocaleDateString('en-US', options); } // Close modal on outside click window.onclick = function(event) { if (event.target == modal) { closeModal(); } } cancelBtn.addEventListener('click', resetForm); </script> </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Device Manager | Apple Style</title>
<!-- Import Google Fonts (San Francisco style approximation) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Font Awesome for Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #007AFF;
--primary-hover: #0056b3;
--danger-color: #FF3B30;
--danger-hover: #d63226;
--success-color: #34C759;
--bg-color: #F5F5F7;
--card-bg: #FFFFFF;
--text-main: #1D1D1F;
--text-secondary: #8E8E93;
--border-color: #D2D2D7;
--shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
--transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
}
[data-theme="dark"] {
--bg-color: #000000;
--card-bg: #1D1D1D;
--text-main: #F5F5F7;
--text-secondary: #8E8E93;
--border-color: #38383A;
--shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background-color: var(--bg-color);
color: var(--text-main);
line-height: 1.5;
transition: var(--transition);
padding: 20px;
}
/* Header Section */
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40px;
flex-wrap: wrap;
gap: 20px;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
}
.brand-icon {
width: 40px;
height: 40px;
background: linear-gradient(135deg, #a1c4fd 0%, #c2e9fb 100%);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
}
h1 {
font-size: 28px;
font-weight: 700;
letter-spacing: -0.5px;
}
.brand-subtitle {
font-size: 14px;
color: var(--text-secondary);
font-weight: 400;
}
.controls {
display: flex;
gap: 15px;
align-items: center;
}