const form = document.getElementById('device-settings-form'); const saveButton = document.getElementById('device-settings-save'); const message = document.getElementById('device-settings-message'); const deviceList = document.getElementById('device-list'); const deviceCount = document.getElementById('device-count'); const createDeviceButton = document.getElementById('create-device-button'); const newDeviceName = document.getElementById('new-device-name'); const rotateKeyButton = document.getElementById('rotate-key-button'); const requestSyncButton = document.getElementById('request-sync-button'); const deleteDeviceButton = document.getElementById('delete-device-button'); const copyCredentialsButton = document.getElementById('copy-credentials-button'); const selectedSummary = { name: document.getElementById('selected-device-name'), portalDefault: document.getElementById('selected-device-default'), lastSeen: document.getElementById('selected-device-last-seen'), lastSync: document.getElementById('selected-device-last-sync'), }; const credentialFields = { serverUrl: document.getElementById('credential-server-url'), deviceName: document.getElementById('credential-device-name'), apiKey: document.getElementById('credential-api-key'), }; const fields = { owner_name: document.getElementById('owner_name'), car_model: document.getElementById('car_model'), device_name: document.getElementById('device_name'), avatar_path: document.getElementById('avatar_path'), }; // Read-only display field — populated from server config, never sent on save. // Odometer is Pi→Server only: the Pi pushes its baseline, the portal just shows it. const odometerField = document.getElementById('odometer_baseline'); let devices = []; let selectedDeviceId = null; let initialState = null; let latestApiKey = ''; function showMessage(text, kind) { message.className = `alert alert-${kind}`; message.textContent = text; message.hidden = false; } function hideMessage() { message.hidden = true; } function formatDate(isoString) { if (!isoString) return '—'; return new Date(isoString).toLocaleString(); } function currentState() { return { owner_name: fields.owner_name.value.trim(), car_model: fields.car_model.value.trim(), device_name: fields.device_name.value.trim(), avatar_path: fields.avatar_path.value.trim(), }; } function setFormEnabled(enabled) { for (const field of Object.values(fields)) { field.disabled = !enabled; } rotateKeyButton.disabled = !enabled; requestSyncButton.disabled = !enabled; deleteDeviceButton.disabled = !enabled; updateDirtyState(); } function updateDirtyState() { if (!initialState || selectedDeviceId === null) { saveButton.disabled = true; return; } saveButton.disabled = JSON.stringify(currentState()) === JSON.stringify(initialState); } function renderDeviceList() { deviceCount.textContent = String(devices.length); if (!devices.length) { deviceList.innerHTML = '