feat: Enter to save, Escape to discard, auto-save on unit/group selection
- selectUnit/selectGroup now async; call autoSaveCurrentForm before switching - Enter in any form field (except textarea) triggers save - Escape restores form to snapshot (discards unsaved changes) - discardUnitForm/discardGroupForm helpers for snapshot restore
This commit is contained in:
@@ -214,7 +214,9 @@
|
||||
});
|
||||
|
||||
// ── Selection ────────────────────────────────────────────────────────────────
|
||||
function selectUnit(unit: Unit) {
|
||||
async function selectUnit(unit: Unit) {
|
||||
const ok = await autoSaveCurrentForm();
|
||||
if (!ok) return;
|
||||
selectedItem = { type: 'unit', id: unit.id };
|
||||
unitForm = { ...unit };
|
||||
unitFormSnapshot = { ...unit };
|
||||
@@ -226,7 +228,9 @@
|
||||
formSuccess = null;
|
||||
}
|
||||
|
||||
function selectGroup(group: Group) {
|
||||
async function selectGroup(group: Group) {
|
||||
const ok = await autoSaveCurrentForm();
|
||||
if (!ok) return;
|
||||
selectedItem = { type: 'group', id: group.id };
|
||||
groupForm = { ...group };
|
||||
groupFormSnapshot = { ...group };
|
||||
@@ -446,6 +450,40 @@
|
||||
await loadData();
|
||||
}
|
||||
|
||||
// ── Keyboard shortcuts for forms ─────────────────────────────────────────────
|
||||
function discardUnitForm() {
|
||||
unitForm = { ...unitFormSnapshot };
|
||||
unitFieldError = null;
|
||||
formError = null;
|
||||
formSuccess = null;
|
||||
}
|
||||
|
||||
function discardGroupForm() {
|
||||
groupForm = { ...groupFormSnapshot };
|
||||
groupFieldError = null;
|
||||
formError = null;
|
||||
formSuccess = null;
|
||||
}
|
||||
|
||||
function onUnitFormKeydown(e: KeyboardEvent) {
|
||||
// Don't intercept Enter inside textareas
|
||||
if (e.key === 'Enter' && (e.target as HTMLElement).tagName !== 'TEXTAREA') {
|
||||
e.preventDefault();
|
||||
saveUnit();
|
||||
} else if (e.key === 'Escape') {
|
||||
discardUnitForm();
|
||||
}
|
||||
}
|
||||
|
||||
function onGroupFormKeydown(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter' && (e.target as HTMLElement).tagName !== 'TEXTAREA') {
|
||||
e.preventDefault();
|
||||
saveGroup();
|
||||
} else if (e.key === 'Escape') {
|
||||
discardGroupForm();
|
||||
}
|
||||
}
|
||||
|
||||
// ── Unit save/delete ─────────────────────────────────────────────────────────
|
||||
async function saveUnit() {
|
||||
formError = null;
|
||||
@@ -817,6 +855,8 @@
|
||||
{/if}
|
||||
|
||||
{#if selectedItem?.type === 'unit' || unitFormNew}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div onkeydown={onUnitFormKeydown}>
|
||||
<h3>{unitFormNew ? 'New Unit' : 'Edit Unit'}</h3>
|
||||
<label>
|
||||
ID {#if !unitFormNew}<small class="muted">(readonly)</small>{/if}
|
||||
@@ -871,8 +911,11 @@
|
||||
<button class="outline secondary" onclick={deleteUnit}>Delete</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div><!-- /onkeydown unit form -->
|
||||
|
||||
{:else if selectedItem?.type === 'group' || groupFormNew}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div onkeydown={onGroupFormKeydown}>
|
||||
<h3>{groupFormNew ? 'New Group' : 'Edit Group'}</h3>
|
||||
<label>
|
||||
ID {#if !groupFormNew}<small class="muted">(readonly)</small>{/if}
|
||||
@@ -926,6 +969,7 @@
|
||||
>Delete</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div><!-- /onkeydown group form -->
|
||||
|
||||
{:else}
|
||||
<p class="select-hint">Select a unit or group to edit, or add a new one.</p>
|
||||
|
||||
Reference in New Issue
Block a user