// Step 3 — Photo guide. // // Shows the same five-bullet tips list the desktop displays, plus the // pre-bundled sample photo as a concrete "like this" example so the // user knows exactly what they're aiming for. Two actions at the // bottom: a primary "Open Camera" (preferred path — feeds the live // capture coach with level + distance gates) and a secondary ghost // link "Upload from photos" for users with a usable shot already in // the camera roll. Upload bypasses the capture step entirely and // hands the file straight to the confirm step. import { session, resetForRetake } from "../session.js"; export default { mount(container, nav) { container.innerHTML = `

Step 2 of 4

Photo Guidance

  • Place a card of standard credit card size beside your hand.
  • Hold phone directly above hand, parallel to table.
  • Use flat, plain background, a sheet of paper works great.
Like this — hand flat, card beside it.
Example photo: hand flat with a credit card placed beside it
`; container.querySelector(".step-back").addEventListener("click", nav.back); container.querySelector(".step-next").addEventListener("click", nav.next); const fileInput = container.querySelector("#guideFileInput"); const errorEl = container.querySelector("#guideUploadError"); const showUploadError = (msg) => { if (!errorEl) return; errorEl.textContent = msg; errorEl.hidden = false; }; const clearUploadError = () => { if (!errorEl) return; errorEl.hidden = true; errorEl.textContent = ""; }; container.querySelector(".guide-upload").addEventListener("click", () => { clearUploadError(); // Reset value so picking the same file twice still fires `change`. fileInput.value = ""; fileInput.click(); }); fileInput.addEventListener("change", (ev) => { const file = ev.target.files && ev.target.files[0]; if (!file) return; // `accept="image/*"` is a hint, not enforcement — Android's "Files" // picker lets users pick anything. Validate at source so the // downstream confirm/measure steps don't render a broken image // or POST garbage and surface a backend 4xx. if (!file.type.startsWith("image/") || file.size === 0) { showUploadError("Please pick an image file (JPG or PNG)."); return; } // Drop any prior session image (camera capture or earlier upload) // so the confirm step sees a clean slate. resetForRetake(); session.imageBlob = file; session.imageUrl = URL.createObjectURL(file); session.imageSource = "upload"; // Skip the capture step — uploads bypass the live coach by design. nav.goTo("confirm"); }); }, };