Jewellery Quotation - GBJ — Final (Centered Headings)
Jewellery Quotation — GBJ
Disc. Diamond (%)
Disc. Making (%)
Flat Making (%)
Disc. Mk (Wt)
Add SKUs to create quotation cards.
`; const win = window.open('', '_blank'); if(!win) return alert('Pop-up blocked. Allow pop-ups to print.'); win.document.write(html); win.document.close(); setTimeout(()=>{ win.focus(); win.print(); }, 600); } /* MAIN RENDER — updated info-grid pairs (center heading above middle grid) */ function renderQuotes(){ const container = document.getElementById("quoteContainer"); container.innerHTML = ""; if(!Array.isArray(allQuotes) || allQuotes.length === 0){ const ph = document.createElement('div'); ph.id='placeholderMsg'; ph.style.background='#fff'; ph.style.padding='18px'; ph.style.borderRadius='10px'; ph.style.boxShadow='0 6px 18px rgba(2,6,23,0.04)'; ph.style.textAlign='center'; ph.style.color='var(--muted)'; ph.innerText='Add SKUs to create quotation cards.'; container.appendChild(ph); document.getElementById("summaryWrap").style.display = "none"; document.getElementById("pvTotal").innerText='₹0'; document.getElementById("pvCount").innerText='0'; if(!isTypingInInput()) ensureSkuFocus(); return; } let totalGold=0,totalDia=0,totalStone=0,totalMaking=0,totalOthers=0; let totGross=0,totNet=0,totDiaWt=0,totStnWt=0; const enableMaking = !!document.getElementById("enableMakingDiscount").checked; const enableDiamond = !!document.getElementById("enableDiamondDiscount").checked; const makingDiscountPercent = enableMaking ? parseFloat(document.getElementById("makingDiscountInput").value || "0") : 0; const diamondDiscountPercent = enableDiamond ? parseFloat(document.getElementById("diamondDiscountInput").value || "0") : 0; const enableFlatMaking = !!document.getElementById("enableFlatMaking").checked; const flatMakingPercent = enableFlatMaking ? parseFloat(document.getElementById("flatMakingPercentInput").value || "0") : 0; const enableMakingPerWt = !!document.getElementById("enableMakingPerWt").checked; const makingPerWtValue = parseFloat(document.getElementById("makingPerWtInput").value || "0"); allQuotes.forEach((data) => { const gold = parseAmount(data["gold amount"] || data["goldamount"] || data["gold"] || data["gld"] ); const diaRaw = parseAmount(data["dia. amount"] || data["diamond amount"] || data["dia amount"] || data["dia"]); const diaWtVal = parseAmount(data["dia.wt."] || data["dia wt"] || data["diawt"]); const hasDiamondWeight = diaWtVal > 0; const hasDiamondPrice = diaRaw > 0; const stn = parseAmount(data["st. amount"] || data["stone amount"] || data["stn amount"] || data["stn"]); const others = parseAmount(data["others amount"] || data["other charges"] || data["others"]) || 0; const netWt = parseAmount(data["net.wt."] || data["net wt"] || data["net"] || data["netwt"]); const grossWt = parseAmount(data["gr.wt."] || data["gr.wt"] || data["gross wt"] || data["gr.wt."]); let makingBase = parseAmount(data["making amount"] || data["makingcharge"] || data["making"] ); let making = (!isNaN(makingBase) && makingBase > 0) ? makingBase : 0; if(enableFlatMaking && !isNaN(flatMakingPercent) && flatMakingPercent > 0 && gold > 0){ making = gold * (flatMakingPercent / 100); } let makingDiscount = 0; // % discount if (enableMaking && !enableFlatMaking && making > 0) { makingDiscount += making * (makingDiscountPercent / 100); } // ✅ PER WEIGHT DISCOUNT (YOUR LOGIC) if (enableMakingPerWt && netWt > 0 && makingPerWtValue > 0) { makingDiscount += netWt * makingPerWtValue; } const makingAfter = Math.max(0, making - makingDiscount); const diaDiscount = (enableDiamond && diaRaw > 0) ? (diaRaw * (diamondDiscountPercent / 100)) : 0; const diaAfter = Math.max(0, diaRaw - diaDiscount); const subtotal = gold + diaAfter + stn + makingAfter + others; const gst = Math.round(subtotal * 0.03); const mrp = subtotal + gst; if(gold > 0) totalGold += gold; if(diaAfter > 0) totalDia += diaAfter; if(stn > 0) totalStone += stn; if(makingAfter > 0) totalMaking += makingAfter; if(others > 0) totalOthers += others; if(grossWt > 0) totGross += grossWt; if(netWt > 0) totNet += netWt; totDiaWt += parseAmount(data["dia.wt."] || data["dia wt"] || data["diawt"]); totStnWt += parseAmount(data["stn.wt."] || data["stn wt"] || data["stnwt"]); const cert = (data["cert.no."] || data["cert no"] || data["cert"] || "").trim(); let certLink = ""; if(cert){ const isDGLA = cert.toLowerCase().startsWith("k1"); const link = isDGLA ? `https://www.dgla.co/online-tools/${cert}` : `https://www.igi.org/verify-your-report/?r=${cert}`; certLink = `${cert}`; } const color = (data["color"] || data["colour"] || "").trim(); const clarity = (data["clarity"] || "").trim(); const colorClarityHtml = (color || clarity) ? `${color}${clarity ? ' | ' + clarity : ''}` : ''; let makingPercentDisplay = ""; if(netWt > 0 && gold > 0){ const pct = (makingAfter / gold) * 100; makingPercentDisplay = `${pct.toFixed(2)} %`; } else if(data["making percent"] || data["making %"]) { makingPercentDisplay = (data["making percent"] || data["making %"]); } const showDiaDiscountRow = enableDiamond && diaDiscount > 0; const showMakingDiscountRow = (enableMaking || enableMakingPerWt) && makingDiscount > 0; /* Build info grid as paired tiles (two columns) to match Image 2 */ const pairs = []; function p(k, v){ return `
${k}
${v}
`; } // helper: treat value as present only when non-empty and not a dash or "0" function hasValue(x){ if(x === undefined || x === null) return false; const s = String(x).trim(); if(s === '' || s === '-' || s === '—') return false; // treat "0" as missing for these display fields (change if you want to show zero) if(s === '0' || s === '0.0' || s === '0.00') return false; return true; } function pushIf(k, v){ if(hasValue(v)) pairs.push(p(k, v)); } // source values (use the same keys you have) const grossVal = data['gr.wt.'] || data['gr.wt'] || data['gross wt']; const netVal = data['net.wt.'] || data['net wt'] || data['net'] || data['netwt']; const diaVal = data['dia.wt.'] || data['dia wt'] || data['diawt']; const stnVal = data['stn.wt.'] || data['stn wt'] || data['stnwt']; const makVal = makingPercentDisplay || (data['making percent']||data['making %']); const certVal = certLink || ''; const colClVal = colorClarityHtml || ''; const sizeVal = data['size'] || ''; // push only when present pushIf('Gross Weight', grossVal); pushIf('Net Weight', netVal); pushIf('Diamond Weight', diaVal); pushIf('Stone Weight', stnVal); pushIf('Making %', makVal); pushIf('Certificate', certVal); pushIf('Colour / Clarity', colClVal); pushIf('Size', sizeVal); // Only show the centered heading when there is at least one tile const infoItemsHtml = (pairs.length > 0) ? `
Weight & Certification
` : ''; const priceRowsHtml = [ '
Price Breakdown
', `
Gold Amount
₹ ${Math.round(gold).toLocaleString()}
`, (diaRaw > 0 ? `
Diamond Amount
₹ ${Math.round(diaAfter).toLocaleString()}
` : ''), (stn > 0 ? `
Stone Amount
₹ ${Math.round(stn).toLocaleString()}
` : ''), (showDiaDiscountRow ? `
Discount (Diamond)
-₹ ${Math.round(diaDiscount).toLocaleString()}
` : ''), (making > 0 ? `
Making Charges
₹ ${Math.round(makingAfter).toLocaleString()}
` : ''), (showMakingDiscountRow ? `
Discount (Making)
-₹ ${Math.round(makingDiscount).toLocaleString()}
` : ''), (others > 0 ? `
Other Charges
₹ ${Math.round(others).toLocaleString()}
` : ''), `
GST (3%)
₹ ${Math.round(gst).toLocaleString()}
` ].join(''); const card = document.createElement("div"); card.className = "card" + (hasDiamondWeight && !hasDiamondPrice ? " missing-diamond-price" : ""); card.setAttribute('data-uid', data._uid); card.innerHTML = `
SKU: ${escapeHtml(data["sku"] || '')} ${ (data["item name"] || data["item"] || data["name"]) ? ' — ' + escapeHtml(data["item name"] || data["item"] || data["name"]) : '' } ${ data["carat"] ? ' — ' + escapeHtml(data["carat"]) + ' Gold' : '' }
${infoItemsHtml}
${pairs.join('')}
${priceRowsHtml}
MRP (Incl. GST)
₹ ${Math.round(mrp).toLocaleString()}
MRP (Incl. GST)
₹ ${Math.round(mrp).toLocaleString()}
`; const delBtn = card.querySelector('.deleteCard'); delBtn && delBtn.addEventListener('click', ()=>{ deleteQuoteByUid(data._uid); }); container.appendChild(card); }); if(allQuotes.length > 0){ document.getElementById("summaryWrap").style.display = "flex"; const totals = computeTotalsFromQuotes(allQuotes); const setRow = (id, has, value) => { const el=document.getElementById(id); if(!el) return; el.style.display = has ? '' : 'none'; if(value!==undefined) el.querySelectorAll('span')[1].innerText = value; }; setRow('rowGross', totals.g>0, totals.g?totals.g.toFixed(3)+' gm':'—'); setRow('rowNet', totals.n>0, totals.n?totals.n.toFixed(3)+' gm':'—'); setRow('rowDiaWt', totals.dw>0, totals.dw?totals.dw.toFixed(2)+' ct':'—'); setRow('rowStnWt', totals.sw>0, totals.sw?totals.sw.toFixed(2)+' ct':'—'); setRow('rowMakingPct', totals.avgMakingPct>0, totals.avgMakingPct?totals.avgMakingPct.toFixed(2)+' %':'—'); setRow('rowGold', totals.totalGold>0, totals.totalGold? '₹ ' + Math.round(totals.totalGold).toLocaleString() : '—'); setRow('rowDiaAmt', totals.totalDia>0, totals.totalDia? '₹ ' + Math.round(totals.totalDia).toLocaleString() : '—'); setRow('rowStnAmt', totals.totalStone>0, totals.totalStone? '₹ ' + Math.round(totals.totalStone).toLocaleString() : '—'); setRow('rowMak', totals.totalMaking>0, totals.totalMaking? '₹ ' + Math.round(totals.totalMaking).toLocaleString() : '—'); setRow('rowOther', totals.totalOthers>0, totals.totalOthers? '₹ ' + Math.round(totals.totalOthers).toLocaleString() : '—'); setRow('rowGst', totals.gst>0, '₹ ' + Math.round(totals.gst).toLocaleString()); setRow('rowTotal', totals.grand>0, '₹ ' + Math.round(totals.grand).toLocaleString()); let sumDiaDiscountText = '—'; if(document.getElementById("enableDiamondDiscount").checked && totals.totalDia>0){ const pct = parseFloat(document.getElementById("diamondDiscountInput").value||"0"); if(pct>0){ const denom = 1 - (pct/100); const orig = denom>0?Math.round(totals.totalDia/denom):totals.totalDia; const diff = Math.round(orig - totals.totalDia); if(diff>0) sumDiaDiscountText = '-₹ ' + diff.toLocaleString(); } } let sumMakDiscountText = '—'; if(document.getElementById("enableMakingDiscount").checked && !document.getElementById("enableFlatMaking").checked && totals.totalMaking>0){ const pct = parseFloat(document.getElementById("makingDiscountInput").value||"0"); if(pct>0){ const denom = 1 - (pct/100); const orig = denom>0?Math.round(totals.totalMaking/denom):totals.totalMaking; const diff = Math.round(orig - totals.totalMaking); if(diff>0) sumMakDiscountText = '-₹ ' + diff.toLocaleString(); } } const rowDiaDiscEl = document.getElementById('rowDiaDisc'); if(rowDiaDiscEl){ if(sumDiaDiscountText!=='—'){ rowDiaDiscEl.style.display=''; rowDiaDiscEl.querySelectorAll('span')[1].innerText = sumDiaDiscountText; } else rowDiaDiscEl.style.display='none'; } const rowMakDiscEl = document.getElementById('rowMakDisc'); if(rowMakDiscEl){ if(sumMakDiscountText!=='—'){ rowMakDiscEl.style.display=''; rowMakDiscEl.querySelectorAll('span')[1].innerText = sumMakDiscountText; } else rowMakDiscEl.style.display='none'; } document.getElementById("pvTotal").innerText = '₹ ' + Math.round(totals.grand).toLocaleString(); document.getElementById("pvCount").innerText = String(allQuotes.length); } else { document.getElementById("summaryWrap").style.display = "none"; document.getElementById("pvCount").innerText = '0'; } // only focus SKU input if user is NOT actively typing elsewhere if(!isTypingInInput()) ensureSkuFocus(); } /* --- KEYBOARD & FOCUS BEHAVIOR (softened) --- */ function wireSkuEnter(){ const skuEl = document.getElementById('skuInput'); if(!skuEl) return; if(skuEl._enterHandler) skuEl.removeEventListener('keydown', skuEl._enterHandler); skuEl._isComposing = false; skuEl.addEventListener('compositionstart', ()=> skuEl._isComposing = true); skuEl.addEventListener('compositionend', ()=> skuEl._isComposing = false); skuEl._enterHandler = function(e){ const isEnter = (e.key === 'Enter' || e.keyCode === 13); if(!isEnter) return; if(e.isComposing || skuEl._isComposing) return; if(e.preventDefault) e.preventDefault(); setTimeout(()=> { handleScannedInput(); }, 0); }; skuEl.addEventListener('keydown', skuEl._enterHandler, {passive:false}); // Global handler: only focus SKU input if user is NOT typing in another control if(!window._skuGlobalHandler){ window._skuGlobalHandler = function(e){ // If activeElement is a form control, do not steal focus if(isTypingInInput()) return; // Otherwise focus the SKU input so scanners send keystrokes there ensureSkuFocus(); }; window.addEventListener('keydown', window._skuGlobalHandler, {passive:true}); } // Click handler: only focus SKU input when clicking outside interactive controls if(!window._skuClickHandler){ window._skuClickHandler = function(ev){ const target = ev.target; // if clicked inside input/select/textarea/button/a or contenteditable, do NOT refocus if(target.closest && target.closest('input, textarea, select, button, a, [contenteditable="true"]')) return; // otherwise focus SKU (use small timeout to let any click-driven focus change settle) setTimeout(()=>{ if(!isTypingInInput()) ensureSkuFocus(); }, 10); }; document.addEventListener('click', window._skuClickHandler, {passive:true}); } // when window regains focus, focus SKU only if user not typing in another input window.addEventListener('focus', ()=> { if(!isTypingInInput()) ensureSkuFocus(); }); } /* init */ window.addEventListener('load', ()=>{ document.getElementById('enableFlatMaking').addEventListener('change', onFlatMakingToggle); document.getElementById('enableMakingDiscount').addEventListener('change', onMakingDiscountToggle); loadCSV().then(()=>{ wireSkuEnter(); if(!isTypingInInput()) ensureSkuFocus(); }); }); /* misc toggles (same as before) */ function onFlatMakingToggle(){ const flat=document.getElementById('enableFlatMaking').checked; const makeChk=document.getElementById('enableMakingDiscount'); const makeInput=document.getElementById('makingDiscountInput'); if(flat){ makeChk.checked=false; makeInput.disabled=true; makeInput.style.opacity=0.6; } else { makeInput.disabled=false; makeInput.style.opacity=1; } renderQuotes(); } function onMakingDiscountToggle(){ const makChk=document.getElementById('enableMakingDiscount').checked; const flatChk=document.getElementById('enableFlatMaking'); const flatInput=document.getElementById('flatMakingPercentInput'); if(makChk){ flatChk.checked=false; flatInput.disabled=true; flatInput.style.opacity=0.6; } else { flatInput.disabled=false; flatInput.style.opacity=1; } renderQuotes(); } /* debug */ window._debug = { csvData, allQuotes, loadCSV, renderQuotes, deleteQuoteByUid, shareCardImage, showLoader, handleScannedInput, wireSkuEnter, isTypingInInput };
BACK TO TOP