summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--public/css/style.css38
-rw-r--r--views/admin/person_detail.erb32
2 files changed, 41 insertions, 29 deletions
diff --git a/public/css/style.css b/public/css/style.css
index a549143..b907f0e 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -571,35 +571,29 @@ tr.delete-marked td { background: rgba(192,57,43,.08); }
.person-detail-main,
.person-page-main { flex: 1; min-width: 0; }
-/* Selectable cards (photo grid and face grid) */
-.selectable-card,
-.selectable-face { cursor: pointer; position: relative; }
-.selectable-card .thumb-wrap,
-.selectable-face .face-detail-thumb { position: relative; }
+/* Selectable photo cards (public person page) */
+.selectable-card { cursor: pointer; position: relative; }
+.selectable-card .thumb-wrap { position: relative; }
.select-checkbox {
position: absolute; top: 6px; left: 6px;
width: 20px; height: 20px; border-radius: 4px;
- border: 2px solid rgba(255,255,255,.7);
- background: rgba(0,0,0,.35);
- display: flex; align-items: center; justify-content: center;
- opacity: 0; transition: opacity .12s;
- pointer-events: none;
+ border: 2px solid rgba(255,255,255,.7); background: rgba(0,0,0,.35);
+ opacity: 0; transition: opacity .12s; pointer-events: none;
}
-.selectable-card:hover .select-checkbox,
-.selectable-face:hover .select-checkbox { opacity: 1; }
-.selectable-card.selected .select-checkbox,
-.selectable-face.selected .select-checkbox {
+.selectable-card:hover .select-checkbox { opacity: 1; }
+.selectable-card.selected .select-checkbox {
opacity: 1; background: var(--accent); border-color: var(--accent);
}
-.selectable-card.selected .select-checkbox::after {
- content: ''; display: block;
- width: 5px; height: 9px;
- border: 2px solid #fff; border-top: none; border-left: none;
- transform: rotate(45deg) translate(-1px, -1px);
+.selectable-card.selected .thumb-wrap img { opacity: .75; }
+.selectable-card.selected { outline: 2px solid var(--accent); outline-offset: -2px; }
+
+/* Selectable face cards (admin cluster detail) */
+.selectable-face { cursor: pointer; }
+.face-cb {
+ display: block; margin: 5px auto 0; width: 16px; height: 16px;
+ cursor: pointer; accent-color: var(--accent);
}
-.selectable-card.selected .thumb-wrap img,
-.selectable-face.selected .face-detail-thumb img { opacity: .75; }
-.selectable-card.selected,
+.selectable-face.selected .face-detail-thumb img { opacity: .72; }
.selectable-face.selected { outline: 2px solid var(--accent); outline-offset: -2px; }
/* ── Admin upload ──────────────────────────────────────────────────────── */
diff --git a/views/admin/person_detail.erb b/views/admin/person_detail.erb
index fbce8af..10319cf 100644
--- a/views/admin/person_detail.erb
+++ b/views/admin/person_detail.erb
@@ -128,8 +128,8 @@
<img src="/face/<%= ERB::Util.html_escape(rel) %>?box=<%= ERB::Util.html_escape(box.join(',')) %>"
width="100" height="100" loading="lazy">
</a>
- <span class="select-checkbox" aria-hidden="true"></span>
</div>
+ <input type="checkbox" class="face-cb" aria-label="Select face">
</div>
<% end %>
</div>
@@ -170,21 +170,39 @@
document.getElementById('bulk-form').style.display = n ? '' : 'none';
}
+ function toggleCard(card, cb, force) {
+ var checked = (force !== undefined) ? force : !cb.checked;
+ cb.checked = checked;
+ var key = card.dataset.entry;
+ if (checked) { selected.add(key); card.classList.add('selected'); }
+ else { selected.delete(key); card.classList.remove('selected'); }
+ updatePanel();
+ }
+
document.querySelectorAll('.selectable-face').forEach(function (card) {
+ var cb = card.querySelector('.face-cb');
+
+ // Checkbox change is the authoritative source of truth
+ cb.addEventListener('change', function () {
+ toggleCard(card, cb, cb.checked);
+ });
+
+ // Clicking anywhere on the card except the image link also toggles
card.addEventListener('click', function (e) {
- if (e.target.closest('.face-photo-link') && !e.target.closest('.select-checkbox')) return;
+ if (e.target.closest('.face-photo-link')) return;
+ if (e.target === cb) return; // let the checkbox handle it natively
e.preventDefault();
- var key = card.dataset.entry;
- if (selected.has(key)) { selected.delete(key); card.classList.remove('selected'); }
- else { selected.add(key); card.classList.add('selected'); }
- updatePanel();
+ toggleCard(card, cb);
});
});
document.getElementById('bulk-clear').addEventListener('click', function (e) {
e.preventDefault();
selected.clear();
- document.querySelectorAll('.selectable-face.selected').forEach(function (c) { c.classList.remove('selected'); });
+ document.querySelectorAll('.selectable-face').forEach(function (c) {
+ c.querySelector('.face-cb').checked = false;
+ c.classList.remove('selected');
+ });
updatePanel();
});