/* Checkout bridge only: approved commercial functions in dtf-site.html stay intact. */ (() => { const box = document.createElement('section'); box.style.cssText = 'position:relative;z-index:20;background:#152026;color:#e6f4f7;padding:12px 24px;font:14px system-ui;border-bottom:2px solid #00b8da'; box.innerHTML = 'Ambiente local · pagamento simulado
'; document.body.prepend(box); const status = document.getElementById('local-status'); const actions = document.getElementById('local-actions'); let busy = false; let draftId = localStorage.getItem('dtf-quote'); let requestKey = localStorage.getItem('dtf-request-key'); let requestBody = localStorage.getItem('dtf-request-body'); const api = async (path, body) => { const response = await fetch('/api'+path, { credentials: 'same-origin', headers: {'Content-Type':'application/json'}, ...(body === undefined ? {} : {method:'POST', body:JSON.stringify(body)}) }); const data = await response.json(); if (!response.ok) { const error=new Error(typeof data.detail === 'string' ? data.detail : 'Confira os dados do pedido ('+response.status+').');error.status=response.status;throw error; } return data; }; const ready = api('/session'); window.dtfSessionReady=ready; window.dtfApi=api; ready.catch(error => { status.textContent = error.message; }); function message(text) { status.textContent = ' · '+text; } function button(label, handler) { const el = document.createElement('button'); el.textContent = label; el.style.cssText = 'margin:8px 8px 0 0;padding:8px 14px;cursor:pointer'; el.onclick = handler; actions.append(el); return el; } async function upload(file) { const session=await ready; return window.dtfUpload(file,{api,progress:message,scope:session.cart_scope}); } window.dtfFreight = async () => { const cep = entrega.cep; try { const result = await api('/freight',{service:'mock-standard',postal_code:cep}); if (entrega.cep !== cep || entrega.tipo !== 'frete') return; entrega.valor = result.total_cents/100; entrega.cotado = true; $('cepMsg').textContent = 'Frete simulado local: '+rs(entrega.valor)+'. Nenhuma transportadora foi consultada.'; pintaEntrega(); } catch(error) { $('cepMsg').textContent = error.message; } }; window.dtfCheckout = async () => { if (busy) return; if (draftId) { await refresh(); box.scrollIntoView(); return; } if (!clienteOk() || !entrega.cotado) return; const cart = [...pedido,...(itemAtual?[itemAtual]:[])]; if (!cart.length) return message('Adicione um item ao pedido.'); busy = true; $('bPagar').disabled = true; try { await ready; if((await api('/session')).cart_scope !== (await ready).cart_scope) throw new Error('Sua conta ou sessão mudou. Recarregue a página antes de enviar o carrinho.'); const items=[]; for (const item of cart) { if (!item.localFiles?.length) throw new Error('Selecione novamente os arquivos deste item.'); const uploads=[]; for (const file of item.localFiles) uploads.push(await upload(file)); items.push({mode:item.modo, metres:String(item.metros), grade:item.nota, uploads}); } const content = {customer:{...cliente},items,freight:{service:entrega.tipo==='retira'?'pickup':'mock-standard',postal_code:entrega.tipo==='retira'?'':entrega.cep}}; const serialized = JSON.stringify(content); if (!requestKey || serialized !== requestBody) { requestKey = crypto.randomUUID(); requestBody = serialized; localStorage.setItem('dtf-request-key',requestKey); localStorage.setItem('dtf-request-body',requestBody); } const quote = await api('/quotes',{request_key:requestKey,...content}); draftId=quote.id; localStorage.setItem('dtf-quote',draftId); await refresh(); box.scrollIntoView({behavior:'smooth'}); } catch(error) { message(error.message); } finally { busy=false; pintaEntrega(); } }; async function refresh() { if (!draftId) return; try { await ready; const quote=await api('/quotes/'+draftId); actions.replaceChildren(); if (quote.status==='pending_review') { message('Arquivos enviados. No Kanban, confira metragem e nota e aprove a cotação '+draftId.slice(0,8)+'.'); } else if (quote.status==='approved') { message('Total validado no servidor: '+rs(quote.approved.total_cents/100)+' · inclui frete. Cotação válida por 24 horas.'); button('Criar pedido pago local',async event=>{ event.target.disabled=true; try { const order=await api('/orders/dev-paid',{quote_id:draftId}); pedido=[]; itemAtual=null; limpaPaineis(); await window.dtfClearCart?.(); message('Pedido local #'+order.number+' pago e disponível no Kanban.'); await refresh(); } catch(error) { message(error.message); event.target.disabled=false; } }); } else if (quote.status==='paid') { message('Pedido local #'+quote.order.number+' pago · etapa: '+quote.order.state+'. Nenhuma cobrança real.'); button('Novo pedido local',()=>{localStorage.removeItem('dtf-quote');localStorage.removeItem('dtf-request-key');localStorage.removeItem('dtf-request-body');location.reload();}); } else { message('Cotação expirada. Envie o carrinho para uma nova revisão.'); button('Nova cotação',()=>{draftId=null;requestKey=null;localStorage.removeItem('dtf-quote');localStorage.removeItem('dtf-request-key');actions.replaceChildren();}); } } catch(error) { message(error.message); actions.replaceChildren(); button('Limpar referência local e tentar de novo',()=>{draftId=null;requestKey=null;localStorage.removeItem('dtf-quote');localStorage.removeItem('dtf-request-key');actions.replaceChildren();}); } } // Explicit refresh avoids replacing focused payment controls during interaction. const refreshButton = document.createElement('button'); refreshButton.textContent='Atualizar pedido local'; refreshButton.style.cssText='margin-left:12px;padding:6px;cursor:pointer'; refreshButton.onclick=refresh; box.append(refreshButton); const portalLink=document.createElement('a');portalLink.href='/portal.html';portalLink.textContent='Minha conta e pedidos'; portalLink.style.cssText='color:#e6f4f7;margin-left:16px;text-decoration:underline';box.append(portalLink); const quoteFromPortal=new URLSearchParams(location.search).get('quote'); if(quoteFromPortal && /^[0-9a-f-]{36}$/.test(quoteFromPortal)){draftId=quoteFromPortal;localStorage.setItem('dtf-quote',draftId);} refresh(); })();