fix: harden week-two ordering, artwork and operations

This commit is contained in:
Cauê Faleiros
2026-09-23 10:40:18 -03:00
parent ccc25a2d5d
commit 24013458c9
43 changed files with 1064 additions and 228 deletions

View File

@@ -6,6 +6,23 @@
let draftId = localStorage.getItem('dtf-quote');
let requestKey = localStorage.getItem('dtf-request-key');
let requestBody = localStorage.getItem('dtf-request-body');
let quotedCart = localStorage.getItem('dtf-quote-cart');
let refreshVersion = 0;
function cartSnapshot() {
const items=[...pedido,...(itemAtual?[itemAtual]:[])];
return JSON.stringify({customer:cliente,delivery:entrega,items:items.map(item=>({
mode:item.modo,metres:item.metros,grade:item.nota,production:item.production,
quality:item.qualityStatus,
acknowledged:item.qualityAcknowledged,
files:(item.localFiles||[]).map(file=>({name:file.name,size:file.size,lastModified:file.lastModified}))
}))});
}
function clearDraft() {
draftId=null;quotedCart=null;requestKey=null;requestBody=null;
for(const key of ['dtf-quote','dtf-quote-cart','dtf-request-key','dtf-request-body'])
localStorage.removeItem(key);
actions.replaceChildren();
}
const api = async (path, body) => {
const response = await fetch('/api'+path, {
credentials: 'same-origin', headers: {'Content-Type':'application/json'},
@@ -19,6 +36,12 @@
return data;
};
const ready = api('/session');
ready.then(session=>{
window.dtfUploadMaxBytes=session.max_upload_bytes;
const limit=document.getElementById('zLimite');
if(limit)limit.textContent='Até '+(session.max_upload_bytes/1048576).toFixed(0)+
' MB por arquivo enquanto a verificação de segurança para arquivos grandes é preparada.';
}).catch(()=>{});
window.dtfSessionReady=ready;
window.dtfApi=api;
ready.catch(error => { status.textContent = error.message; });
@@ -50,8 +73,10 @@
if (busy) return;
if (draftId) { await refresh(); status.scrollIntoView({behavior:'smooth',block:'nearest'}); return; }
if (!clienteOk() || !entrega.cotado) return;
if (!cartPodeEnviar()) return message('Revise a qualidade e confirme a ressalva de cada item antes de enviar o pedido.');
const cart = [...pedido,...(itemAtual?[itemAtual]:[])];
if (!cart.length) return message('Adicione um item ao pedido.');
const initialCart=cartSnapshot();
busy = true;
$('bPagar').disabled = true;
try {
@@ -62,9 +87,15 @@
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});
if (item.production?.version!==2 || item.production.sources?.length!==uploads.length)
throw new Error('A montagem deste item precisa ser refeita antes da cotação.');
items.push({mode:item.modo, metres:String(item.metros), grade:item.nota, uploads,
production:{...item.production,sources:item.production.sources.map((source,index)=>({
upload_id:uploads[index],...source}))},
quality_status:item.qualityStatus,quality_acknowledged:item.qualityAcknowledged});
}
const content = {customer:{...cliente},items,freight:{service:entrega.tipo==='retira'?'pickup':'mock-standard',postal_code:entrega.tipo==='retira'?'':entrega.cep}};
if (cartSnapshot()!==initialCart) throw new Error('O carrinho mudou durante o envio. Confira os itens e envie de novo.');
const serialized = JSON.stringify(content);
if (!requestKey || serialized !== requestBody) {
requestKey = crypto.randomUUID(); requestBody = serialized;
@@ -72,6 +103,7 @@
localStorage.setItem('dtf-request-body',requestBody);
}
const quote = await api('/quotes',{request_key:requestKey,...content});
quotedCart=initialCart;localStorage.setItem('dtf-quote-cart',quotedCart);
draftId=quote.id; localStorage.setItem('dtf-quote',draftId);
await refresh();
status.scrollIntoView({behavior:'smooth',block:'nearest'});
@@ -80,10 +112,17 @@
};
async function refresh() {
if (!draftId) return;
const version=++refreshVersion, shownId=draftId;
try {
await ready;
const quote=await api('/quotes/'+draftId);
const quote=await api('/quotes/'+shownId);
if(version!==refreshVersion || draftId!==shownId) return;
actions.replaceChildren();
if (quote.status!=='paid' && (!quotedCart || quotedCart!==cartSnapshot())) {
message('O carrinho mudou ou não está disponível neste navegador. A cotação anterior continua separada; envie o carrinho atual para uma nova revisão.');
button('Enviar carrinho atual',()=>{clearDraft();window.dtfCheckout();});
return;
}
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') {
@@ -93,6 +132,7 @@
return;
}
button('Criar pedido de teste',async event=>{
if (!quotedCart || quotedCart!==cartSnapshot()) { await refresh(); return; }
event.target.disabled=true;
try {
const order=await api('/orders/dev-paid',{quote_id:draftId});
@@ -104,18 +144,23 @@
});
} else if (quote.status==='paid') {
message('Pedido #'+quote.order.number+' · etapa: '+quote.order.state+'.');
button('Novo pedido',()=>{localStorage.removeItem('dtf-quote');localStorage.removeItem('dtf-request-key');localStorage.removeItem('dtf-request-body');location.reload();});
button('Novo pedido',()=>{clearDraft();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();});
button('Nova cotação',clearDraft);
}
} catch(error) {
if(version!==refreshVersion || draftId!==shownId) return;
message(error.message);
actions.replaceChildren();
button('Limpar referência e tentar de novo',()=>{draftId=null;requestKey=null;localStorage.removeItem('dtf-quote');localStorage.removeItem('dtf-request-key');actions.replaceChildren();});
button('Limpar referência e tentar de novo',clearDraft);
}
}
const quoteFromPortal=new URLSearchParams(location.search).get('quote');
if(quoteFromPortal && /^[0-9a-f-]{36}$/.test(quoteFromPortal)){draftId=quoteFromPortal;localStorage.setItem('dtf-quote',draftId);}
if(quoteFromPortal && /^[0-9a-f-]{36}$/.test(quoteFromPortal)){
if(draftId!==quoteFromPortal){quotedCart=null;localStorage.removeItem('dtf-quote-cart');}
draftId=quoteFromPortal;localStorage.setItem('dtf-quote',draftId);
}
window.addEventListener('dtf-cart-changed',()=>{if(draftId) refresh();});
refresh();
})();