1export const MENSAGEM_ESTOQUE_PREFIXO = 'Desculpe. No momento, temos apenas'; 2 3export function mensagemEstoqueInsuficiente(estoqueDisponivel) { 4 return `${MENSAGEM_ESTOQUE_PREFIXO} ${estoqueDisponivel} unidades deste item em estoque.`; 5} 6 7export function formatarMoeda(valor) { 8 return `R$ ${Number(valor).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; 9} 10 11export function calcularValorOriginal(preco) { 12 if (!preco || !preco.valorDesconto || preco.valorDesconto <= 0 || preco.subtotal == null) { 13 return null; 14 } 15 return Number(preco.subtotal) + Number(preco.valorDesconto); 16} 17 18export function calcularPercentualDesconto(preco) { 19 const valorOriginal = calcularValorOriginal(preco); 20 if (!valorOriginal || valorOriginal <= 0) { 21 return null; 22 } 23 return Math.round((Number(preco.valorDesconto) / valorOriginal) * 100); 24} 25 26export function createNumberStepper({ 27 container, 28 value = 1, 29 min = 1, 30 max = 999, 31 onChange = () => {}, 32 onInvalid = () => {}, 33 enabled = true, 34}) { 35 container.innerHTML = ''; 36 container.classList.add('number-stepper'); 37 38 let currentValue = Math.max(min, Math.min(max, parseInt(value, 10) || min)); 39 40 const btnMenos = document.createElement('button'); 41 btnMenos.type = 'button'; 42 btnMenos.className = 'btn-stepper btn-txt so-icone btnMenos'; 43 btnMenos.title = 'Subtrair'; 44 btnMenos.innerHTML = '<i class="ic-diminuir-circulo"></i>'; 45 46 const input = document.createElement('input'); 47 input.type = 'number'; 48 input.className = 'stepper-input'; 49 input.min = String(min); 50 input.max = String(max); 51 input.value = String(currentValue); 52 input.setAttribute('aria-label', 'Quantidade'); 53 54 const btnMais = document.createElement('button'); 55 btnMais.type = 'button'; 56 btnMais.className = 'btn-stepper btn-txt so-icone btnMais'; 57 btnMais.title = 'Adicionar'; 58 btnMais.innerHTML = '<i class="ic-adicionar-circulo"></i>'; 59 60 container.appendChild(btnMenos); 61 container.appendChild(input); 62 container.appendChild(btnMais); 63 64 function atualizarBotoes() { 65 btnMenos.disabled = !enabled || currentValue <= min; 66 btnMais.disabled = !enabled || currentValue >= max; 67 input.disabled = !enabled; 68 } 69 70 function aplicarValor(novoValor, validarEstoque = true) { 71 const parsed = parseInt(novoValor, 10); 72 if (Number.isNaN(parsed)) { 73 input.value = String(currentValue); 74 return; 75 } 76 if (parsed < min) { 77 currentValue = min; 78 input.value = String(currentValue); 79 atualizarBotoes(); 80 onChange(currentValue); 81 return; 82 } 83 if (parsed > max && validarEstoque) { 84 input.value = String(currentValue); 85 onInvalid(mensagemEstoqueInsuficiente(max)); 86 return; 87 } 88 currentValue = Math.min(parsed, max); 89 input.value = String(currentValue); 90 atualizarBotoes(); 91 onChange(currentValue); 92 } 93 94 btnMenos.addEventListener('click', () => { 95 if (!enabled || currentValue <= min) { 96 return; 97 } 98 aplicarValor(currentValue - 1, false); 99 }); 100 101 btnMais.addEventListener('click', () => { 102 if (!enabled || currentValue >= max) { 103 if (currentValue >= max) { 104 onInvalid(mensagemEstoqueInsuficiente(max)); 105 } 106 return; 107 } 108 aplicarValor(currentValue + 1, false); 109 }); 110 111 input.addEventListener('change', () => { 112 aplicarValor(input.value, true); 113 }); 114 115 input.addEventListener('blur', () => { 116 aplicarValor(input.value, true); 117 }); 118 119 atualizarBotoes(); 120 121 return { 122 getValue: () => currentValue, 123 setMax: (novoMax) => { 124 max = Math.max(min, parseInt(novoMax, 10) || min); 125 input.max = String(max); 126 if (currentValue > max) { 127 currentValue = max; 128 input.value = String(currentValue); 129 } 130 atualizarBotoes(); 131 }, 132 setValue: (novoValor) => { 133 aplicarValor(novoValor, false); 134 }, 135 setEnabled: (ativo) => { 136 enabled = ativo; 137 atualizarBotoes(); 138 }, 139 }; 140}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.