Răsfoiți Sursa

Add inline PIN edit: account-edit icon expands sub-row with new PIN input

ZiB 4 luni în urmă
părinte
comite
3b4976d88a
1 a modificat fișierele cu 38 adăugiri și 7 ștergeri
  1. 38 7
      custom_components/zlock_slots/frontend/zlock-slots-card.js

+ 38 - 7
custom_components/zlock_slots/frontend/zlock-slots-card.js

@@ -91,6 +91,10 @@ class ZLockSlotsCard extends HTMLElement {
         .empty-note { opacity: 0.5; font-size: 0.85rem; padding: 8px 0; }
         .inline-edit { display: flex; gap: 6px; align-items: center; }
         .inline-edit input { flex: 1; }
+        .pin-edit-row td { padding: 0 8px 6px; }
+        .pin-edit-row .pin-edit { display: flex; gap: 8px; align-items: center; }
+        .pin-edit-row label { font-size: 0.8rem; opacity: 0.7; white-space: nowrap; }
+        .name-display { cursor: text; }
       </style>
       <ha-card>
         <div class="section">
@@ -116,7 +120,7 @@ class ZLockSlotsCard extends HTMLElement {
                         </button>
                       </td>
                       <td>
-                        <span id="name-display-${s.slot_num}">
+                        <span id="name-display-${s.slot_num}" class="name-display" data-action="edit-name" data-slot="${s.slot_num}" title="Click to edit name">
                           ${s.name ?? '<em style="opacity:.4">unnamed</em>'}
                         </span>
                         <span class="inline-edit" id="name-edit-${s.slot_num}" style="display:none">
@@ -125,7 +129,7 @@ class ZLockSlotsCard extends HTMLElement {
                       </td>
                       <td>
                         <span style="display:flex;gap:4px;align-items:center">
-                          <button class="icon-btn" data-action="edit-name" data-slot="${s.slot_num}" title="Edit name">
+                          <button class="icon-btn" data-action="edit-pin" data-slot="${s.slot_num}" title="Change PIN">
                             <ha-icon icon="mdi:account-edit"></ha-icon>
                           </button>
                           <button class="icon-btn clear-btn" data-action="clear" data-slot="${s.slot_num}" title="Clear slot ${s.slot_num}">
@@ -134,6 +138,14 @@ class ZLockSlotsCard extends HTMLElement {
                         </span>
                       </td>
                     </tr>
+                    <tr class="pin-edit-row" id="pin-edit-row-${s.slot_num}" style="display:none">
+                      <td colspan="4">
+                        <div class="pin-edit">
+                          <label>New PIN</label>
+                          <input id="pin-input-${s.slot_num}" type="password" minlength="4" maxlength="8" placeholder="4–8 digits — Enter to save, Esc to cancel" data-slot="${s.slot_num}" data-type="pin" />
+                        </div>
+                      </td>
+                    </tr>
                   `).join("")}
                 </tbody>
               </table>`
@@ -188,6 +200,13 @@ class ZLockSlotsCard extends HTMLElement {
           const input = root.getElementById(`name-input-${slot}`);
           input.focus();
           input.select();
+
+        } else if (action === "edit-pin") {
+          const row = root.getElementById(`pin-edit-row-${slot}`);
+          const input = root.getElementById(`pin-input-${slot}`);
+          row.style.display = "";
+          input.value = "";
+          input.focus();
         }
       });
     });
@@ -198,23 +217,35 @@ class ZLockSlotsCard extends HTMLElement {
       return save;
     };
 
+    const closePin = (slot) => {
+      root.getElementById(`pin-edit-row-${slot}`).style.display = "none";
+    };
+
     root.querySelectorAll("input[data-slot]").forEach(input => {
       const slot = parseInt(input.dataset.slot, 10);
+      const isPin = input.dataset.type === "pin";
 
       input.addEventListener("keydown", async (e) => {
         if (e.key === "Enter") {
           e.preventDefault();
           input.removeEventListener("blur", input._blurHandler);
-          const name = input.value.trim();
-          closeName(slot, true);
-          await this._callService("set_name", { lock_entity_id: lock, slot, name });
+          if (isPin) {
+            const code = input.value;
+            if (code.length < 4 || code.length > 8) return;
+            closePin(slot);
+            await this._callService("set_code", { lock_entity_id: lock, slot, code });
+          } else {
+            const name = input.value.trim();
+            closeName(slot, true);
+            await this._callService("set_name", { lock_entity_id: lock, slot, name });
+          }
         } else if (e.key === "Escape") {
           input.removeEventListener("blur", input._blurHandler);
-          closeName(slot, false);
+          isPin ? closePin(slot) : closeName(slot, false);
         }
       });
 
-      input._blurHandler = () => closeName(slot, false);
+      input._blurHandler = () => isPin ? closePin(slot) : closeName(slot, false);
       input.addEventListener("blur", input._blurHandler);
     });