Fix mobile camera fallback and scanner theme
This commit is contained in:
@@ -94,6 +94,8 @@ function sellForm(id="") {
|
|||||||
bindCustomer(form);form.onsubmit=async e=>{e.preventDefault();const button=e.submitter,selected=checks.filter(x=>x.checked);if(!selected.length){toast("Select at least one product.");return;}button.disabled=true;const data=Object.fromEntries(new FormData(form));delete data.productIds;data.items=selected.map(check=>({productId:check.value,salePrice:Number(form.querySelector(`[data-price="${check.value}"]`).value)||0}));try{await change("/api/sales","POST",data,`${selected.length} ${selected.length===1?"item":"items"} sold.`);}finally{button.disabled=false}};$("[data-cancel]").onclick=closeModal;
|
bindCustomer(form);form.onsubmit=async e=>{e.preventDefault();const button=e.submitter,selected=checks.filter(x=>x.checked);if(!selected.length){toast("Select at least one product.");return;}button.disabled=true;const data=Object.fromEntries(new FormData(form));delete data.productIds;data.items=selected.map(check=>({productId:check.value,salePrice:Number(form.querySelector(`[data-price="${check.value}"]`).value)||0}));try{await change("/api/sales","POST",data,`${selected.length} ${selected.length===1?"item":"items"} sold.`);}finally{button.disabled=false}};$("[data-cancel]").onclick=closeModal;
|
||||||
}
|
}
|
||||||
async function submitForm(e,path,message,method="POST"){ e.preventDefault(); await change(path,method,Object.fromEntries(new FormData(e.currentTarget)),message); }
|
async function submitForm(e,path,message,method="POST"){ e.preventDefault(); await change(path,method,Object.fromEntries(new FormData(e.currentTarget)),message); }
|
||||||
|
// Re-declared here to keep camera access available on Safari, where BarcodeDetector may be absent.
|
||||||
|
async function scanLabelCompat(form,help){if(!navigator.mediaDevices?.getUserMedia){help.textContent="Camera access is unavailable. Use manual entry or enable camera access for this site.";return}let stream,overlay;try{stream=await navigator.mediaDevices.getUserMedia({video:{facingMode:{ideal:"environment"}}});const video=document.createElement("video");video.autoplay=true;video.playsInline=true;video.srcObject=stream;overlay=document.createElement("div");overlay.className="scanner-overlay";overlay.innerHTML='<div><strong>Point at the full label</strong><small>This browser can show the camera but cannot decode barcodes automatically. Enter the three values below, then close this view.</small><button type="button">Close camera</button></div>';overlay.prepend(video);document.body.append(overlay);const finish=()=>{stream.getTracks().forEach(track=>track.stop());overlay.remove()};overlay.querySelector("button").onclick=finish;await video.play();help.textContent="Camera is open. Enter the identifiers below, then close this view."}catch(error){if(stream)stream.getTracks().forEach(track=>track.stop());if(overlay)overlay.remove();help.textContent="Unable to open the camera. Check browser permissions or enter the identifiers manually."}}
|
||||||
async function change(path,method,body,message){ try{ await api(path,{method,body:body?JSON.stringify(body):undefined}); closeModal(); await load(); toast(message); }catch(e){ toast(e.message); } }
|
async function change(path,method,body,message){ try{ await api(path,{method,body:body?JSON.stringify(body):undefined}); closeModal(); await load(); toast(message); }catch(e){ toast(e.message); } }
|
||||||
|
|
||||||
function viewSale(p) {
|
function viewSale(p) {
|
||||||
@@ -166,5 +168,6 @@ $("#logout").onclick=logout;
|
|||||||
$("#themeSelect").onchange=e=>{try{localStorage.setItem("vboxstock-theme",e.target.value)}catch{}applyTheme(e.target.value);};
|
$("#themeSelect").onchange=e=>{try{localStorage.setItem("vboxstock-theme",e.target.value)}catch{}applyTheme(e.target.value);};
|
||||||
systemTheme.addEventListener?.("change",()=>{if(savedTheme()==="system")applyTheme("system")});
|
systemTheme.addEventListener?.("change",()=>{if(savedTheme()==="system")applyTheme("system")});
|
||||||
$("#date").textContent=new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"});
|
$("#date").textContent=new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"});
|
||||||
|
if(!("BarcodeDetector" in window))document.addEventListener("click",e=>{const button=e.target.closest(".scan-camera");if(button){e.stopPropagation();scanLabelCompat(button.closest("form"),button.closest("form").querySelector(".scan-help"))}},true);
|
||||||
applyTheme();
|
applyTheme();
|
||||||
initialize();
|
initialize();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ th{background:var(--surface-table);color:var(--muted-2)}th,td,.records nav,.back
|
|||||||
.customer-notes article,.backup-list,.user-list,.model-list,.warranty-list,.audit-list{border-color:var(--border)}
|
.customer-notes article,.backup-list,.user-list,.model-list,.warranty-list,.audit-list{border-color:var(--border)}
|
||||||
.model-list article{border-color:var(--border)}.model-summary small{color:var(--muted)}.model-status.active{background:var(--green-soft);color:var(--green)}.model-status.archived{background:var(--surface-soft);color:var(--muted)}
|
.model-list article{border-color:var(--border)}.model-summary small{color:var(--muted)}.model-status.active{background:var(--green-soft);color:var(--green)}.model-status.archived{background:var(--surface-soft);color:var(--muted)}
|
||||||
.warranty-list article,.conditional-fields,.sale-items,.sale-item{border-color:var(--border)}.conditional-fields,.sale-summary{background:var(--surface-soft)}.sale-item small,.sale-summary span,.conditional-hint{color:var(--muted)}.conditional-hint{border-color:var(--border-strong)}.field-help{color:var(--muted)}.warranty-pill.in-warranty{background:var(--green-soft);color:var(--green)}.warranty-pill.expired{background:var(--danger-soft);color:var(--danger)}.warranty-pill.neutral{background:var(--surface-soft);color:var(--muted)}
|
.warranty-list article,.conditional-fields,.sale-items,.sale-item{border-color:var(--border)}.conditional-fields,.sale-summary{background:var(--surface-soft)}.sale-item small,.sale-summary span,.conditional-hint{color:var(--muted)}.conditional-hint{border-color:var(--border-strong)}.field-help{color:var(--muted)}.warranty-pill.in-warranty{background:var(--green-soft);color:var(--green)}.warranty-pill.expired{background:var(--danger-soft);color:var(--danger)}.warranty-pill.neutral{background:var(--surface-soft);color:var(--muted)}
|
||||||
|
.scan-panel,.scanner-overlay,.scanner-overlay input,.scanner-overlay select,.scanner-overlay textarea{color:var(--text)}.scan-panel{background:var(--surface-soft);border-color:var(--border)}.scan-panel input,.scan-panel select,.scan-panel textarea{background:var(--surface);border-color:var(--border-strong);color:var(--text)}.scanner-overlay{background:#000c}.scanner-overlay>div{background:var(--surface);color:var(--text);border:1px solid var(--border)}.scanner-overlay button{background:var(--blue);color:#fff}
|
||||||
.filter-bar{border-color:var(--border);background:var(--surface-soft)}.filter-bar .button{background:var(--surface);border:1px solid var(--border-strong);color:var(--text)}.customer-match{color:var(--blue-text)!important}.diagnostic-grid article,.automatic-backups{background:var(--surface-soft);border-color:var(--border)}.diagnostic-grid span,.diagnostic-grid small,.automatic-backups p,.backup-schedule-status{color:var(--muted)}.export-links .button{background:var(--surface-soft);border:1px solid var(--border-strong);color:var(--text)}
|
.filter-bar{border-color:var(--border);background:var(--surface-soft)}.filter-bar .button{background:var(--surface);border:1px solid var(--border-strong);color:var(--text)}.customer-match{color:var(--blue-text)!important}.diagnostic-grid article,.automatic-backups{background:var(--surface-soft);border-color:var(--border)}.diagnostic-grid span,.diagnostic-grid small,.automatic-backups p,.backup-schedule-status{color:var(--muted)}.export-links .button{background:var(--surface-soft);border:1px solid var(--border-strong);color:var(--text)}
|
||||||
.note-category{background:var(--blue-soft);color:var(--blue-text)}.backup-warning{background:var(--warning-soft);border-color:color-mix(in srgb,var(--warning) 40%,transparent);color:var(--warning)}
|
.note-category{background:var(--blue-soft);color:var(--blue-text)}.backup-warning{background:var(--warning-soft);border-color:color-mix(in srgb,var(--warning) 40%,transparent);color:var(--warning)}
|
||||||
.auth-screen{background:linear-gradient(145deg,color-mix(in srgb,var(--blue) 10%,var(--page)),var(--page))}.auth-card{box-shadow:0 22px 60px var(--shadow)}
|
.auth-screen{background:linear-gradient(145deg,color-mix(in srgb,var(--blue) 10%,var(--page)),var(--page))}.auth-card{box-shadow:0 22px 60px var(--shadow)}
|
||||||
|
|||||||
Reference in New Issue
Block a user