fix: save button stuck — version sequencing; add Ignore button to not-found people

This commit is contained in:
James 2026-03-20 00:53:53 -04:00
parent fb1a4fdaba
commit e0910a943b
1 changed files with 22 additions and 13 deletions

View File

@ -280,6 +280,17 @@
btn.disabled = true; btn.textContent = 'Saving...'; errEl.classList.add('hidden');
try {
const version = parseInt(document.getElementById('eVersion').value) || 1;
// Single write: details + members together via members endpoint first, then details
// Actually: save details (which preserves existing members in orgData), then members
// To avoid version race, save members FIRST then details (or combine)
// Simplest: save members first with current version, details second with version+1
const mRes = await fetchAPI('/api/orgs/' + editingOrgId + '/members', {
method: 'PUT',
body: JSON.stringify({ members: editingMembers, version })
});
const mData = await mRes.json();
if (!mRes.ok) throw new Error(mData.error || 'Failed to save members');
const newVersion = mData.version || version + 1;
const res = await fetchAPI('/api/orgs/' + editingOrgId, {
method: 'PUT',
body: JSON.stringify({
@ -293,25 +304,16 @@
address: document.getElementById('eAddress').value.trim(),
state: document.getElementById('eState').value.trim(),
logo: document.getElementById('eLogo').value.trim(),
version,
version: newVersion,
})
});
const data = await res.json();
if (!res.ok) throw new Error(data.error || 'Failed to save');
// Also save members separately
await saveMembersToServer(data.version || version + 1);
if (!res.ok) throw new Error(data.error || 'Failed to save details');
closeEditModal();
loadOrgs();
} catch(e) { errEl.textContent = e.message; errEl.classList.remove('hidden'); btn.disabled = false; btn.textContent = 'Save Changes'; }
}
async function saveMembersToServer(version) {
await fetchAPI('/api/orgs/' + editingOrgId + '/members', {
method: 'PUT',
body: JSON.stringify({ members: editingMembers, version })
});
}
// ---- Members Tab ----
function renderMemberList() {
const list = document.getElementById('memberList');
@ -463,12 +465,13 @@
+ '<p class="text-xs mb-2" style="color:var(--ds-tx3)">They may have left the organization. Review and remove individually if confirmed.</p>'
+ '<div class="space-y-1.5">';
notFound.forEach((p, i) => {
html += '<div class="flex items-center gap-3 px-3 py-2 rounded-lg" style="background:rgba(245,158,11,0.05);border:1px solid rgba(245,158,11,0.15)">'
html += '<div id="nf-row-' + i + '" class="flex items-center gap-3 px-3 py-2 rounded-lg" style="background:rgba(245,158,11,0.05);border:1px solid rgba(245,158,11,0.15)">'
+ '<div class="flex-1 min-w-0">'
+ '<div class="text-sm truncate" style="color:var(--ds-tx)">' + escHtml(p.name || p.email) + '</div>'
+ (p.title ? '<div class="text-xs truncate text-amber-400">' + escHtml(p.title) + '</div>' : '')
+ '</div>'
+ '<span class="text-xs text-amber-400 shrink-0 mr-2">Not on site</span>'
+ '<span class="text-xs text-amber-400 shrink-0 mx-2">Not on site</span>'
+ '<button onclick="ignoreInactive(' + i + ')" class="shrink-0 px-2 py-1 rounded text-xs transition hover:opacity-80 mr-1" style="background:var(--ds-hv);color:var(--ds-tx2)">Ignore</button>'
+ '<button onclick="confirmRemoveInactive(' + i + ')" class="shrink-0 px-2 py-1 rounded text-xs transition hover:opacity-80" style="background:rgba(239,68,68,0.1);color:#ef4444;border:1px solid rgba(239,68,68,0.2)">Remove</button>'
+ '</div>';
});
@ -491,6 +494,12 @@
const sa = document.getElementById('rescrapeSelectAll');
if (sa) sa.checked = all.length > 0 && checked.length === all.length;
}
function ignoreInactive(idx) {
const row = document.getElementById('nf-row-' + idx);
if (row) row.remove();
if (window._rescrapeNotFound) window._rescrapeNotFound[idx] = null;
}
function confirmRemoveInactive(idx) {
const people = window._rescrapeNotFound || [];
const p = people[idx];