/*
* photo.js
* Photo upload for all entity types and the mobile Photo Queue feature.
*
* Photo upload:
* triggerPhoto(type, id) — opens the hidden file input, sets _photoTarget.
* The 'change' handler uploads via multipart POST, updates the tree node,
* and on mobile automatically runs the full AI pipeline for books
* (POST /api/books/{id}/process).
*
* Photo Queue (mobile-only UI):
* collectQueueBooks(node, type) — collects all non-approved books in tree
* order (top-to-bottom within each shelf, left-to-right across shelves).
* renderPhotoQueue() — updates the #photo-queue-overlay DOM in-place.
* Queue flow: show spine → tap camera → upload + process → auto-advance.
* Queue is stored in _photoQueue (state.js) so events.js can control it.
*
* Depends on: S, _photoQueue (state.js); req, toast (api.js / helpers.js);
* walkTree, findNode, esc (tree-render.js / helpers.js);
* isDesktop, render (helpers.js / init.js)
* Provides: collectQueueBooks(), renderPhotoQueue(), triggerPhoto()
*/
// ── Photo Queue ──────────────────────────────────────────────────────────────
function collectQueueBooks(node, type) {
const books = [];
function collect(n, t) {
if (t === 'book') {
if (n.identification_status !== 'user_approved') books.push(n);
return;
}
if (t === 'room') n.cabinets.forEach(c => collect(c, 'cabinet'));
if (t === 'cabinet') n.shelves.forEach(s => collect(s, 'shelf'));
if (t === 'shelf') n.books.forEach(b => collect(b, 'book'));
}
collect(node, type);
return books;
}
function renderPhotoQueue() {
const el = document.getElementById('photo-queue-overlay');
if (!el) return;
if (!_photoQueue) { el.style.display = 'none'; el.innerHTML = ''; return; }
const {books, index, processing} = _photoQueue;
el.style.display = 'flex';
if (index >= books.length) {
el.innerHTML = `
Photo Queue
✓
All done!
All ${books.length} book${books.length !== 1 ? 's' : ''} photographed
`;
return;
}
const book = books[index];
el.innerHTML = `