860 lines
37 KiB
JavaScript
860 lines
37 KiB
JavaScript
var INDICADORES = [
|
|
{ pilar: "PILAR ARQUITETURA", indicador: "Fotos da Fachada (letreiro luminoso com acessibilidade)", penalidade: "GRAVISSIMA", peso: 4, maxFotos: 1 },
|
|
{ pilar: "PILAR ARQUITETURA", indicador: "Fotos de todos equipamentos", detalhe: "Mobiliario, gondolas, tela digital, caixa, mesas, cavalete, baianas e coringa.", penalidade: "GRAVE", peso: 3, maxFotos: 8 },
|
|
{ pilar: "PILAR ARQUITETURA", indicador: "Fotos da iluminacao (luzes da vitrine e interior da loja)", penalidade: "GRAVE", peso: 3, maxFotos: 2 },
|
|
{ pilar: "PILAR ARQUITETURA", indicador: "Foto do coletor de embalagem (Botirecicla)", penalidade: "MEDIA", peso: 2, maxFotos: 1 },
|
|
{ pilar: "PILAR ARQUITETURA", indicador: "Fotos dos mobshops da loja", penalidade: "MEDIA", peso: 2, maxFotos: 2 },
|
|
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto da vitrine (identificando todas comunicacoes)", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Fotos enquadrando cada sessao", detalhe: "Feminina, masculina, infantil, cuidados, cabelos, presentes e maquiagem.", penalidade: "GRAVE", peso: 3, maxFotos: 7 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Fotos das comunicacoes destaques e storytelling", detalhe: "Feminina, masculina e cuidados.", penalidade: "GRAVE", peso: 3, maxFotos: 3 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto das embalagens", penalidade: "MEDIA", peso: 2, maxFotos: 1 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto do QR-Code de politica de privacidade", penalidade: "GRAVISSIMA", peso: 4, maxFotos: 1 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto do codigo de defesa do consumidor", penalidade: "GRAVISSIMA", peso: 4, maxFotos: 1 },
|
|
{ pilar: "PILAR VISUAL MERCHANDISING", indicador: "Foto do verso da tela digital", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
|
|
|
|
{ pilar: "PILAR EXPOSIÇÃO", indicador: "Fotos das datas de validade dos produtos", detalheBullets: [
|
|
"# Produtos O Boticario",
|
|
"Cooffe Woman",
|
|
"Linha Casa 214",
|
|
"5 itens da linha Botik",
|
|
"Dr. Botica",
|
|
"Portinari",
|
|
"Celebre",
|
|
"Floratta",
|
|
"Arbo",
|
|
"Shampoo e Condicionador - Linha Match",
|
|
"5 provadores de Make B",
|
|
"5 provadores da linha Intense",
|
|
"# Produtos QDB?",
|
|
"2 itens da linha Instamatte",
|
|
"Protetor solar facial",
|
|
"Corretivo liquido",
|
|
"Mascara para cilios",
|
|
"10 batons hidratantes",
|
|
"Shampoo e Condicionador Au.migos"
|
|
], penalidade: "GRAVISSIMA", peso: 4, maxFotos: 22 },
|
|
{ pilar: "PILAR EXPOSIÇÃO", indicador: "Foto dos aplicadores descartaveis", penalidade: "MEDIA", peso: 2, maxFotos: 1 },
|
|
{ pilar: "PILAR EXPOSIÇÃO", indicador: "Foto da exposição da sessão Make.B", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
|
|
{ pilar: "PILAR EXPOSIÇÃO", indicador: "Foto da exposição da sessão Intense", penalidade: "GRAVE", peso: 3, maxFotos: 1 },
|
|
|
|
{ pilar: "PILAR UNIFORME", indicador: "Fotos dos uniformes (do pescoco para baixo)", penalidade: "GRAVE", peso: 3, maxFotos: 2 },
|
|
{ pilar: "PILAR INFORMATIVA", indicador: "Foto do espaco onde ficam os produtos destinados a logistica", penalidade: "NAO PONTUA", peso: 0, maxFotos: 1 }
|
|
];
|
|
|
|
var FATORES = {
|
|
"CONFORME": 1,
|
|
"NAO_CONFORME": 0
|
|
};
|
|
var ALLOWED_EXT = { "pdf": true, "jpg": true, "jpeg": true, "png": true };
|
|
var REQUIRE_ATTACHMENT = false; // mude para true para voltar a exigir anexo
|
|
var CURRENT_PROFILE = "LOJA";
|
|
var KNOWN_ATTACHMENT_KEYS = {};
|
|
// Ajuste os codigos de atividade do seu processo aqui.
|
|
var FLOW_CONFIG = {
|
|
lojaStates: [0, 4],
|
|
analistaStates: [5]
|
|
};
|
|
|
|
function badgeClass(penalidade) {
|
|
if (penalidade === "GRAVISSIMA") return "danger";
|
|
if (penalidade === "GRAVE") return "warning";
|
|
if (penalidade === "MEDIA") return "info";
|
|
if (penalidade === "LEVE") return "default";
|
|
return "primary";
|
|
}
|
|
|
|
function getClassificacao(score) {
|
|
if (score >= 90) return "Excelente";
|
|
if (score >= 80) return "Bom";
|
|
if (score >= 70) return "Regular";
|
|
return "Critico";
|
|
}
|
|
|
|
function toTitleCase(text) {
|
|
var s = String(text || "").toLowerCase().trim();
|
|
if (!s) return "";
|
|
var words = s.split(/\s+/);
|
|
for (var i = 0; i < words.length; i++) {
|
|
var w = words[i];
|
|
if (!w) continue;
|
|
words[i] = w.charAt(0).toUpperCase() + w.slice(1);
|
|
}
|
|
return words.join(" ");
|
|
}
|
|
|
|
function indicadorCountLabel(n) {
|
|
return n === 1 ? "1 indicador" : (n + " indicadores");
|
|
}
|
|
|
|
function renderDetalhe(item) {
|
|
if (Array.isArray(item.detalheBullets) && item.detalheBullets.length) {
|
|
var html = "<div class='indicador-help'><ul>";
|
|
for (var i = 0; i < item.detalheBullets.length; i++) {
|
|
var txt = String(item.detalheBullets[i] || "");
|
|
if (txt.indexOf("# ") === 0) {
|
|
html += "<li class='indicador-group'>" + escapeHtml(txt.substring(2)) + "</li>";
|
|
} else {
|
|
html += "<li>" + escapeHtml(txt) + "</li>";
|
|
}
|
|
}
|
|
html += "</ul></div>";
|
|
return html;
|
|
}
|
|
if (item.detalhe) {
|
|
return "<div class='indicador-help'>" + escapeHtml(item.detalhe) + "</div>";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function getResumoPilaresHtml() {
|
|
var rows = [
|
|
{ nome: "Arquitetura", texto: "Fachada da loja e estrutura física, evidenciando marca, iluminação, acessibilidade, equipamentos e estado geral do ambiente." },
|
|
{ nome: "Visual Merchandising", texto: "Vitrine e área interna com comunicação vigente, padrão visual, organização, embalagens corretas e bom estado dos materiais." },
|
|
{ nome: "Exposição", texto: "Exposição de produtos em vitrine e interior, com precificação, validade visível, testes, preenchimento de prateleiras e uso de aplicadores." },
|
|
{ nome: "Uniforme", texto: "Equipe em atendimento com uso correto de uniforme, calçados e acessórios conforme padrão estabelecido." },
|
|
{ nome: "Informativa", texto: "Ambiente com foco em informações operacionais, logística reversa, armazenamento de materiais e comunicação de serviços." }
|
|
];
|
|
var html = "<div class='pilar-summary-card'><div class='summary-title'>Guia dos Pilares</div>";
|
|
for (var i = 0; i < rows.length; i++) {
|
|
html += "<div class='summary-item'><span class='summary-name'>" + escapeHtml(rows[i].nome) + ":</span> " + escapeHtml(rows[i].texto) + "</div>";
|
|
}
|
|
html += "</div>";
|
|
return html;
|
|
}
|
|
|
|
function buildAnexoInputs(index, maxFotos) {
|
|
var total = parseInt(maxFotos, 10);
|
|
if (isNaN(total) || total < 1) total = 1;
|
|
var html = "<div class='anexo-multi-list'>";
|
|
for (var i = 1; i <= total; i++) {
|
|
var anexoId = "anexo_" + index + "_" + i;
|
|
var anexoFileName = "EVID_" + index + "_F" + i;
|
|
var extraClass = i > 2 ? " extra-slot" : "";
|
|
html += ""
|
|
+ "<div class='anexo-slot" + extraClass + "'>"
|
|
+ "<div class='anexo-slot-label'>Foto " + i + " de " + total + "</div>"
|
|
+ "<input type='text' class='form-control anexo-plugin' readonly id='" + anexoId + "' name='" + anexoId + "' data-filename='" + anexoFileName + "' data-accept='image/*,.pdf' data-required='true' />"
|
|
+ "</div>";
|
|
}
|
|
html += "</div>";
|
|
if (total > 2) {
|
|
html += "<div class='anexo-toggle-wrap'><button type='button' class='btn btn-default btn-sm anexo-toggle' data-expanded='false' data-total='" + total + "'>Mostrar todas (" + total + ")</button></div>";
|
|
}
|
|
return html;
|
|
}
|
|
|
|
function buildAuditRow(item, index) {
|
|
var selectResultado = ""
|
|
+ "<select class='form-control resultado'>"
|
|
+ "<option value=''>Selecione</option>"
|
|
+ "<option value='CONFORME'>Conforme</option>"
|
|
+ "<option value='NAO_CONFORME'>Nao Conforme</option>"
|
|
+ "</select>";
|
|
var maxFotos = parseInt(item.maxFotos, 10);
|
|
if (isNaN(maxFotos) || maxFotos < 1) maxFotos = 1;
|
|
var anexosHtml = buildAnexoInputs(index, maxFotos);
|
|
|
|
return ""
|
|
+ "<div class='audit-row' data-pilar='" + escapeHtml(item.pilar) + "' data-indicador='" + escapeHtml(item.indicador) + "' data-penalidade='" + escapeHtml(item.penalidade) + "' data-max-fotos='" + maxFotos + "'>"
|
|
+ "<div class='audit-row-main'>"
|
|
+ "<div class='audit-row-top'>"
|
|
+ "<div class='audit-info'>"
|
|
+ "<div class='indicador-cell'>" + escapeHtml(item.indicador) + "</div>"
|
|
+ renderDetalhe(item)
|
|
+ "</div>"
|
|
+ "<div class='anexos-cell anexo-wrap'>"
|
|
+ anexosHtml
|
|
+ "<div class='anexo-progress'><span class='anexo-progress-count'>0/" + maxFotos + "</span> fotos enviadas</div>"
|
|
+ "<div class='anexo-auto-hint'>Use os botoes de upload/visualizar em cada foto.</div>"
|
|
+ "</div>"
|
|
+ "</div>"
|
|
+ "<div class='meta-grid col-analista'>"
|
|
+ "<div class='meta-box'><div class='meta-label'>Penalidade</div><div class='meta-value'><span class='label label-default penalidade-badge penalidade-status'>Aguardando</span></div></div>"
|
|
+ "<div class='meta-box'><div class='meta-label'>Peso</div><div class='meta-value'><span class='peso'>" + item.peso + "</span></div></div>"
|
|
+ "<div class='meta-box'><div class='meta-label'>Fator</div><div class='meta-value fator'>-</div></div>"
|
|
+ "<div class='meta-box'><div class='meta-label'>Pontuacao</div><div class='meta-value pontuacao'>0</div></div>"
|
|
+ "<div class='meta-box resultado-wrap'><div class='meta-label'>Resultado</div><div class='meta-value'>" + selectResultado + "</div></div>"
|
|
+ "</div>"
|
|
+ "<div class='just-wrap col-analista'><input type='text' class='form-control justificativa' placeholder='Obrigatoria se Nao Conforme' /></div>"
|
|
+ "</div>"
|
|
+ "</div>";
|
|
}
|
|
|
|
function montaTabela() {
|
|
var grupos = {};
|
|
for (var i = 0; i < INDICADORES.length; i++) {
|
|
var item = INDICADORES[i];
|
|
if (!grupos[item.pilar]) grupos[item.pilar] = [];
|
|
grupos[item.pilar].push(item);
|
|
}
|
|
|
|
var pilares = Object.keys(grupos);
|
|
var html = "";
|
|
var rowIndex = 1;
|
|
for (var p = 0; p < pilares.length; p++) {
|
|
var nomePilar = pilares[p];
|
|
var linhas = grupos[nomePilar];
|
|
var openStyle = " style='display:none;'";
|
|
var totalFotosPilar = 0;
|
|
for (var t = 0; t < linhas.length; t++) {
|
|
totalFotosPilar += parseInt(linhas[t].maxFotos, 10) || 0;
|
|
}
|
|
html += "<div class='pilar-panel'>";
|
|
html += "<div class='pilar-head' data-target='pilarBody" + p + "' data-total-fotos='" + totalFotosPilar + "'>";
|
|
html += "<div class='pilar-title-row'><span class='pilar-state-dot state-pending' title='Nao iniciado'>✕</span><span class='pilar-title'>" + escapeHtml(toTitleCase(nomePilar.replace("PILAR ", ""))) + "</span></div>";
|
|
html += "<div class='pilar-photo-row'><span class='pilar-photo-count'>0/" + totalFotosPilar + " fotos</span><span class='pilar-missing'>" + totalFotosPilar + " faltando</span></div>";
|
|
html += "<div class='pilar-mini-track'><span class='pilar-mini-fill'></span></div>";
|
|
html += "<div class='pilar-foot'><span class='pilar-count'>" + indicadorCountLabel(linhas.length) + "</span><span class='pilar-open-cta'>Abrir Pilar →</span></div>";
|
|
html += "</div>";
|
|
html += "<div class='pilar-body' id='pilarBody" + p + "'" + openStyle + ">";
|
|
for (var r = 0; r < linhas.length; r++) {
|
|
html += buildAuditRow(linhas[r], rowIndex);
|
|
rowIndex++;
|
|
}
|
|
html += "</div></div>";
|
|
}
|
|
html += getResumoPilaresHtml();
|
|
|
|
$("#pilaresContainer").html(html);
|
|
}
|
|
|
|
function getExt(fileName) {
|
|
var n = (fileName || "").toLowerCase();
|
|
var pos = n.lastIndexOf(".");
|
|
return pos > -1 ? n.substring(pos + 1) : "";
|
|
}
|
|
|
|
function escapeHtml(text) {
|
|
return String(text || "")
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
function isImageExt(fileName) {
|
|
var ext = getExt(fileName);
|
|
return ext === "jpg" || ext === "jpeg" || ext === "png";
|
|
}
|
|
|
|
function getStateFromUrl(url) {
|
|
var u = String(url || "");
|
|
if (!u) return "";
|
|
var patterns = [
|
|
/(?:\?|&)WKNumState=(\d+)/i,
|
|
/(?:\?|&)state=(\d+)/i,
|
|
/(?:\?|&)stateSequence=(\d+)/i,
|
|
/(?:\?|&)choosedState=(\d+)/i,
|
|
/(?:\?|&)numState=(\d+)/i
|
|
];
|
|
for (var i = 0; i < patterns.length; i++) {
|
|
var m = u.match(patterns[i]);
|
|
if (m && m[1]) return m[1];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
function getCurrentState() {
|
|
var candidates = [];
|
|
try {
|
|
candidates.push(window.WKNumState);
|
|
candidates.push(window.WKCurrentState);
|
|
candidates.push($("input[name='WKNumState']").val());
|
|
candidates.push($("input[name='WKCurrentState']").val());
|
|
candidates.push($("#WKNumState").val());
|
|
candidates.push($("#WKCurrentState").val());
|
|
candidates.push(getStateFromUrl(window.location && window.location.href));
|
|
} catch (e) {}
|
|
|
|
try {
|
|
if (window.parent) {
|
|
candidates.push(window.parent.WKNumState);
|
|
candidates.push(window.parent.WKCurrentState);
|
|
if (window.parent.$) {
|
|
candidates.push(window.parent.$("input[name='WKNumState']").val());
|
|
candidates.push(window.parent.$("input[name='WKCurrentState']").val());
|
|
candidates.push(window.parent.$("#WKNumState").val());
|
|
candidates.push(window.parent.$("#WKCurrentState").val());
|
|
}
|
|
candidates.push(getStateFromUrl(window.parent.location && window.parent.location.href));
|
|
}
|
|
} catch (e2) {}
|
|
|
|
for (var j = 0; j < candidates.length; j++) {
|
|
var parsed = parseInt(String(candidates[j] || "").trim(), 10);
|
|
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function resolveProfileByState(state) {
|
|
for (var i = 0; i < FLOW_CONFIG.analistaStates.length; i++) {
|
|
if (FLOW_CONFIG.analistaStates[i] === state) return "ANALISTA";
|
|
}
|
|
for (var j = 0; j < FLOW_CONFIG.lojaStates.length; j++) {
|
|
if (FLOW_CONFIG.lojaStates[j] === state) return "LOJA";
|
|
}
|
|
try {
|
|
var pageText = (
|
|
$("h1").first().text()
|
|
|| $(".page-header h1").first().text()
|
|
|| (window.parent && window.parent.$ ? window.parent.$("h1").first().text() : "")
|
|
|| ""
|
|
).toLowerCase();
|
|
if (pageText.indexOf("validar planograma") > -1) return "ANALISTA";
|
|
} catch (e) {}
|
|
return "LOJA";
|
|
}
|
|
|
|
function getCurrentUserCode() {
|
|
try {
|
|
if (window.WCMAPI && window.WCMAPI.userCode) return String(window.WCMAPI.userCode);
|
|
} catch (e) {}
|
|
try {
|
|
if (window.parent && window.parent.WCMAPI && window.parent.WCMAPI.userCode) {
|
|
return String(window.parent.WCMAPI.userCode);
|
|
}
|
|
} catch (e2) {}
|
|
return "";
|
|
}
|
|
|
|
function getNaoConformes() {
|
|
var list = [];
|
|
$(".audit-row").each(function () {
|
|
var $tr = $(this);
|
|
if ($tr.find(".resultado").val() === "NAO_CONFORME") {
|
|
list.push({
|
|
pilar: $tr.attr("data-pilar") || "",
|
|
indicador: $tr.attr("data-indicador") || ""
|
|
});
|
|
}
|
|
});
|
|
return list;
|
|
}
|
|
|
|
function renderNaoConformeResumo() {
|
|
var list = getNaoConformes();
|
|
var $box = $("#naoConformeBox");
|
|
var $list = $("#naoConformeList");
|
|
$list.empty();
|
|
if (!list.length) {
|
|
$box.hide();
|
|
return;
|
|
}
|
|
for (var i = 0; i < list.length; i++) {
|
|
var item = list[i] || {};
|
|
var pilar = item.pilar || "";
|
|
var indicador = item.indicador || "";
|
|
var texto = pilar ? (pilar + " - " + indicador) : indicador;
|
|
$list.append(
|
|
"<button type='button' class='nc-item' data-pilar='" + escapeHtml(pilar) + "' data-indicador='" + escapeHtml(indicador) + "'>"
|
|
+ escapeHtml(texto)
|
|
+ "</button>"
|
|
);
|
|
}
|
|
$box.show();
|
|
}
|
|
|
|
function applyProfileUI() {
|
|
var isAnalista = CURRENT_PROFILE === "ANALISTA";
|
|
$(".col-analista").toggle(isAnalista);
|
|
$(".audit-card").toggle(isAnalista);
|
|
$(".resultado").prop("disabled", !isAnalista);
|
|
$(".justificativa").prop("disabled", !isAnalista);
|
|
if (isAnalista) {
|
|
$(".anexo-auto-hint").hide();
|
|
} else {
|
|
$(".anexo-auto-hint").show();
|
|
}
|
|
applyAttachmentActionVisibility();
|
|
$("#profileBadge").text("Perfil: " + (isAnalista ? "Analista" : "Loja") + " (atividade " + getCurrentState() + ")");
|
|
}
|
|
|
|
function updateCompletionStatus() {
|
|
var total = 0;
|
|
var preenchidos = 0;
|
|
$(".anexo-plugin").each(function () {
|
|
total++;
|
|
var nome = ($(this).val() || "").trim();
|
|
if (nome) preenchidos++;
|
|
});
|
|
$("#progressBadge").text("Evidencias: " + preenchidos + "/" + total);
|
|
var perc = total > 0 ? Math.round((preenchidos / total) * 100) : 0;
|
|
$("#globalProgressFill").css("width", perc + "%");
|
|
$("#globalProgressPercent").text(perc + "%");
|
|
$("#globalProgressMeta").text(preenchidos + " de " + total + " fotos enviadas");
|
|
updatePilarProgress();
|
|
}
|
|
|
|
function updateRowAttachmentProgress($row) {
|
|
if (!$row || !$row.length) return;
|
|
var total = 0;
|
|
var preenchidos = 0;
|
|
$row.find(".anexo-slot").each(function () {
|
|
var $slot = $(this);
|
|
var nome = ($slot.find(".anexo-plugin").val() || "").trim();
|
|
total++;
|
|
var temAnexo = !!nome;
|
|
if (temAnexo) preenchidos++;
|
|
$slot.toggleClass("slot-filled", temAnexo);
|
|
});
|
|
$row.find(".anexo-progress-count").text(preenchidos + "/" + total);
|
|
}
|
|
|
|
function updatePilarProgress() {
|
|
$(".pilar-panel").each(function () {
|
|
var $panel = $(this);
|
|
var total = 0;
|
|
var preenchidos = 0;
|
|
$panel.find(".anexo-plugin").each(function () {
|
|
total++;
|
|
if (($(this).val() || "").trim()) preenchidos++;
|
|
});
|
|
var perc = total > 0 ? Math.round((preenchidos / total) * 100) : 0;
|
|
var faltantes = Math.max(0, total - preenchidos);
|
|
$panel.find(".pilar-photo-count").text(preenchidos + "/" + total + " fotos");
|
|
$panel.find(".pilar-missing").text(faltantes > 0 ? (faltantes + " faltando") : "100% concluido");
|
|
$panel.find(".pilar-mini-fill").css("width", perc + "%");
|
|
var $dot = $panel.find(".pilar-state-dot");
|
|
var cls = "state-pending";
|
|
var fillColor = "#9fb2c6";
|
|
var icon = "✕";
|
|
var dotTitle = "Nao iniciado";
|
|
if (total > 0 && preenchidos === total) {
|
|
cls = "state-done";
|
|
fillColor = "#2f9d78";
|
|
icon = "✓";
|
|
dotTitle = "Concluido";
|
|
} else if (preenchidos > 0) {
|
|
cls = "state-progress";
|
|
fillColor = "#d18a2f";
|
|
icon = "⚠";
|
|
dotTitle = "Em andamento";
|
|
}
|
|
$dot.removeClass("state-pending state-progress state-done").addClass(cls).text(icon).attr("title", dotTitle);
|
|
$panel.find(".pilar-mini-fill").css("background", fillColor);
|
|
});
|
|
}
|
|
|
|
function initAttachmentPlugin() {
|
|
if (typeof $.fn.fluigFormAttachment !== "function") {
|
|
FLUIGC.toast({
|
|
title: "Plugin:",
|
|
message: "fluigFormAttachment.js nao foi carregado.",
|
|
type: "warning"
|
|
});
|
|
return;
|
|
}
|
|
$(".anexo-plugin").each(function () {
|
|
var $f = $(this);
|
|
if ($f.data("ffaInit")) return;
|
|
$f.fluigFormAttachment();
|
|
$f.data("ffaInit", true);
|
|
});
|
|
}
|
|
|
|
function applyAttachmentActionVisibility() {
|
|
if (typeof $.fn.fluigFormAttachment !== "function") return;
|
|
var isAnalista = CURRENT_PROFILE === "ANALISTA";
|
|
$(".anexo-plugin").each(function () {
|
|
var $f = $(this);
|
|
if (!$f.data("ffaInit")) return;
|
|
if (isAnalista) {
|
|
$f.fluigFormAttachment("hideActionButton");
|
|
} else {
|
|
$f.fluigFormAttachment("showActionButton");
|
|
}
|
|
});
|
|
}
|
|
|
|
function findNativeSendButtons($root) {
|
|
var $all = $root.find("button, input[type='button'], input[type='submit'], a");
|
|
return $all.filter(function () {
|
|
var $el = $(this);
|
|
var txt = ($el.is("input") ? ($el.val() || "") : ($el.text() || "")).trim().toLowerCase();
|
|
if (!txt) return false;
|
|
return txt === "enviar" || txt.indexOf(" enviar") > -1 || txt.indexOf("enviar ") > -1;
|
|
});
|
|
}
|
|
|
|
function hideNativeSendButtons() {
|
|
try {
|
|
var $local = findNativeSendButtons($(document));
|
|
$local.not("#btnEnviarForm").css("display", "none");
|
|
$local.each(function () {
|
|
var $group = $(this).closest(".btn-group, .btn-toolbar, .btn-group-vertical, .dropup, .dropdown");
|
|
if ($group.length) {
|
|
$group.find(".dropdown-toggle, .btn.dropdown-toggle").css("display", "none");
|
|
}
|
|
});
|
|
} catch (e) {}
|
|
try {
|
|
if (window.parent && window.parent.document) {
|
|
var $parentDoc = $(window.parent.document);
|
|
var $parentBtns = findNativeSendButtons($parentDoc);
|
|
$parentBtns.css("display", "none");
|
|
$parentBtns.each(function () {
|
|
var $group = $(this).closest(".btn-group, .btn-toolbar, .btn-group-vertical, .dropup, .dropdown");
|
|
if ($group.length) {
|
|
$group.find(".dropdown-toggle, .btn.dropdown-toggle").css("display", "none");
|
|
}
|
|
});
|
|
|
|
// Fallback: oculta toggles "soltos" que sobram no split button.
|
|
$parentDoc.find(".dropdown-toggle, .btn.dropdown-toggle").filter(function () {
|
|
var txt = ($(this).text() || "").trim();
|
|
return txt === "" || txt === "▼" || txt === "▾" || txt === "v";
|
|
}).each(function () {
|
|
var $toggle = $(this);
|
|
var $group = $toggle.closest(".btn-group, .btn-toolbar, .btn-group-vertical, .dropup, .dropdown");
|
|
if (!$group.length) return;
|
|
var hasSendRef = findNativeSendButtons($group).length > 0;
|
|
if (hasSendRef) {
|
|
$toggle.css("display", "none");
|
|
}
|
|
});
|
|
}
|
|
} catch (e2) {}
|
|
}
|
|
|
|
function clickNativeSendButton() {
|
|
try {
|
|
var $parentDoc = window.parent && window.parent.document ? $(window.parent.document) : $();
|
|
var $native = findNativeSendButtons($parentDoc).first();
|
|
if ($native.length) {
|
|
$native.trigger("click");
|
|
return true;
|
|
}
|
|
} catch (e) {}
|
|
try {
|
|
var $local = findNativeSendButtons($(document)).not("#btnEnviarForm").first();
|
|
if ($local.length) {
|
|
$local.trigger("click");
|
|
return true;
|
|
}
|
|
} catch (e2) {}
|
|
return false;
|
|
}
|
|
|
|
function syncPayload() {
|
|
var rows = [];
|
|
var naoConformeList = [];
|
|
$(".audit-row").each(function () {
|
|
var $tr = $(this);
|
|
var peso = parseFloat($tr.find(".peso").text()) || 0;
|
|
var resultado = $tr.find(".resultado").val();
|
|
var fator = FATORES[resultado];
|
|
var pontuacao = (typeof fator === "number") ? (peso * fator) : null;
|
|
var anexos = [];
|
|
$tr.find(".anexo-plugin").each(function () {
|
|
var nome = ($(this).val() || "").trim();
|
|
anexos.push(nome);
|
|
});
|
|
var anexosPreenchidos = [];
|
|
for (var a = 0; a < anexos.length; a++) {
|
|
if (anexos[a]) anexosPreenchidos.push(anexos[a]);
|
|
}
|
|
var indicador = $tr.attr("data-indicador") || "";
|
|
if (resultado === "NAO_CONFORME") {
|
|
naoConformeList.push(indicador);
|
|
}
|
|
rows.push({
|
|
pilar: $tr.attr("data-pilar") || "",
|
|
indicador: indicador,
|
|
penalidade: $tr.attr("data-penalidade") || "",
|
|
peso: peso,
|
|
resultado: resultado || "",
|
|
fator: (typeof fator === "number") ? fator : null,
|
|
pontuacao: pontuacao,
|
|
justificativa: ($tr.find(".justificativa").val() || "").trim(),
|
|
anexoSequence: "",
|
|
anexoKey: "",
|
|
anexoNome: anexosPreenchidos.length ? anexosPreenchidos[0] : "",
|
|
anexos: anexos,
|
|
qtdAnexosPreenchidos: anexosPreenchidos.length
|
|
});
|
|
updateRowAttachmentProgress($tr);
|
|
});
|
|
$("#qtdNaoConforme").val(String(naoConformeList.length));
|
|
$("#temNaoConforme").val(naoConformeList.length > 0 ? "true" : "false");
|
|
$("#listaNaoConforme").val(naoConformeList.join(" | "));
|
|
$("#saidaAnalise").val(naoConformeList.length > 0 ? "NAO_CONFORME" : "CONFORME");
|
|
$("#auditoriaPayload").val(JSON.stringify(rows));
|
|
updateCompletionStatus();
|
|
renderNaoConformeResumo();
|
|
}
|
|
|
|
function findRowByIndicador(indicador) {
|
|
var $found = $();
|
|
$(".audit-row").each(function () {
|
|
if ($(this).attr("data-indicador") === indicador) {
|
|
$found = $(this);
|
|
return false;
|
|
}
|
|
});
|
|
return $found;
|
|
}
|
|
|
|
function updatePenalidadeVisual($tr) {
|
|
var resultado = $tr.find(".resultado").val();
|
|
var penalidadeBase = ($tr.attr("data-penalidade") || "").trim();
|
|
var $badge = $tr.find(".penalidade-status");
|
|
var $justWrap = $tr.find(".just-wrap");
|
|
|
|
if (resultado === "CONFORME") {
|
|
$badge
|
|
.removeClass("label-danger label-warning label-info label-primary label-default")
|
|
.addClass("label-success")
|
|
.text("Conforme");
|
|
$justWrap.hide();
|
|
return;
|
|
}
|
|
|
|
if (resultado === "NAO_CONFORME") {
|
|
$badge
|
|
.removeClass("label-success label-danger label-warning label-info label-primary label-default")
|
|
.addClass("label-" + badgeClass(penalidadeBase))
|
|
.text(penalidadeBase || "Nao Conforme");
|
|
$justWrap.show();
|
|
return;
|
|
}
|
|
|
|
$badge
|
|
.removeClass("label-success label-danger label-warning label-info label-primary")
|
|
.addClass("label-default")
|
|
.text("Aguardando");
|
|
$justWrap.hide();
|
|
}
|
|
|
|
function restorePayload() {
|
|
var raw = ($("#auditoriaPayload").val() || "").trim();
|
|
if (!raw) return;
|
|
var data = [];
|
|
try {
|
|
data = JSON.parse(raw);
|
|
if (!Array.isArray(data)) return;
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
for (var i = 0; i < data.length; i++) {
|
|
var saved = data[i];
|
|
var $tr = findRowByIndicador(saved.indicador);
|
|
if (!$tr.length) continue;
|
|
if (saved.resultado) $tr.find(".resultado").val(saved.resultado);
|
|
if (saved.justificativa) $tr.find(".justificativa").val(saved.justificativa);
|
|
if (Array.isArray(saved.anexos)) {
|
|
var $inputs = $tr.find(".anexo-plugin");
|
|
for (var k = 0; k < saved.anexos.length; k++) {
|
|
if (k >= $inputs.length) break;
|
|
if (saved.anexos[k]) {
|
|
$($inputs.get(k)).val(saved.anexos[k]).trigger("change");
|
|
}
|
|
}
|
|
} else if (saved.anexoNome) {
|
|
$tr.find(".anexo-plugin").first().val(saved.anexoNome).trigger("change");
|
|
}
|
|
updatePenalidadeVisual($tr);
|
|
}
|
|
}
|
|
|
|
function recalc() {
|
|
var pontosObtidos = 0;
|
|
var pontosPossiveis = 0;
|
|
|
|
$(".audit-row").each(function () {
|
|
var $tr = $(this);
|
|
var peso = parseFloat($tr.find(".peso").text()) || 0;
|
|
var resultado = $tr.find(".resultado").val();
|
|
var fator = FATORES[resultado];
|
|
var pontuacao = 0;
|
|
updatePenalidadeVisual($tr);
|
|
|
|
if (typeof fator === "number") {
|
|
pontuacao = peso * fator;
|
|
$tr.find(".fator").text(fator.toFixed(2));
|
|
$tr.find(".pontuacao").text(pontuacao.toFixed(2));
|
|
if (peso > 0) {
|
|
pontosPossiveis += peso;
|
|
pontosObtidos += pontuacao;
|
|
}
|
|
} else {
|
|
$tr.find(".fator").text("-");
|
|
$tr.find(".pontuacao").text("0");
|
|
}
|
|
});
|
|
|
|
var score = pontosPossiveis > 0 ? (pontosObtidos / pontosPossiveis) * 100 : 0;
|
|
$("#pontosObtidos").text(pontosObtidos.toFixed(2));
|
|
$("#pontosPossiveis").text(pontosPossiveis.toFixed(2));
|
|
$("#scoreFinal").text(score.toFixed(2) + "%");
|
|
$("#classificacao").text(getClassificacao(score));
|
|
}
|
|
|
|
function validarFormulario() {
|
|
var erros = [];
|
|
$(".audit-row").each(function (idx) {
|
|
var $tr = $(this);
|
|
var resultado = $tr.find(".resultado").val();
|
|
var justificativa = ($tr.find(".justificativa").val() || "").trim();
|
|
var $anexoInputs = $tr.find(".anexo-plugin");
|
|
var indicador = $tr.attr("data-indicador") || "";
|
|
var $resultadoCell = $tr.find(".resultado-wrap");
|
|
var $anexoCell = $tr.find(".anexo-wrap");
|
|
|
|
if (resultado === "NAO_CONFORME" && justificativa.length === 0) {
|
|
erros.push("Linha " + (idx + 1) + " (" + indicador + "): justificativa obrigatoria.");
|
|
$tr.find(".just-wrap").addClass("has-error");
|
|
} else {
|
|
$tr.find(".just-wrap").removeClass("has-error");
|
|
}
|
|
|
|
if (CURRENT_PROFILE === "ANALISTA") {
|
|
if (!resultado) {
|
|
erros.push("Linha " + (idx + 1) + " (" + indicador + "): selecione o resultado.");
|
|
$resultadoCell.addClass("has-error");
|
|
} else {
|
|
$resultadoCell.removeClass("has-error");
|
|
}
|
|
}
|
|
|
|
if (REQUIRE_ATTACHMENT) {
|
|
var hasErrorAnexo = false;
|
|
$anexoInputs.each(function () {
|
|
var $anexoInput = $(this);
|
|
var anexoNome = ($anexoInput.val() || "").trim();
|
|
var hasAttachment = anexoNome.length > 0;
|
|
var isValidAttachment = true;
|
|
if (typeof $.fn.fluigFormAttachment === "function" && $anexoInput.data("ffaInit")) {
|
|
try {
|
|
hasAttachment = $anexoInput.fluigFormAttachment("hasAttachment");
|
|
isValidAttachment = $anexoInput.fluigFormAttachment("isValid");
|
|
} catch (e) {}
|
|
}
|
|
if (!hasAttachment) {
|
|
hasErrorAnexo = true;
|
|
return false;
|
|
}
|
|
if (!isValidAttachment) {
|
|
hasErrorAnexo = true;
|
|
return false;
|
|
}
|
|
if (!ALLOWED_EXT[getExt(anexoNome)]) {
|
|
hasErrorAnexo = true;
|
|
return false;
|
|
}
|
|
});
|
|
if (hasErrorAnexo) {
|
|
erros.push("Linha " + (idx + 1) + " (" + indicador + "): revise os anexos obrigatorios (PDF/JPG/PNG).");
|
|
$anexoCell.addClass("has-error");
|
|
} else {
|
|
$anexoCell.removeClass("has-error");
|
|
}
|
|
} else {
|
|
$anexoCell.removeClass("has-error");
|
|
}
|
|
});
|
|
|
|
syncPayload();
|
|
|
|
if (erros.length > 0) {
|
|
FLUIGC.toast({
|
|
title: "Validacao:",
|
|
message: erros[0],
|
|
type: "warning"
|
|
});
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
$(document).ready(function () {
|
|
var wkState = getCurrentState();
|
|
CURRENT_PROFILE = resolveProfileByState(wkState);
|
|
if (!($("#usuarioRetorno").val() || "").trim()) {
|
|
$("#usuarioRetorno").val(getCurrentUserCode());
|
|
}
|
|
montaTabela();
|
|
initAttachmentPlugin();
|
|
restorePayload();
|
|
applyProfileUI();
|
|
recalc();
|
|
syncPayload();
|
|
$(".audit-row").each(function () {
|
|
updatePenalidadeVisual($(this));
|
|
});
|
|
|
|
$("#pilaresContainer").on("click", ".pilar-head", function () {
|
|
var target = $(this).attr("data-target");
|
|
var $head = $(this);
|
|
var $panel = $head.closest(".pilar-panel");
|
|
$("#" + target).stop(true, true).slideToggle(120, function () {
|
|
var isOpen = $(this).is(":visible");
|
|
$head.toggleClass("is-open", isOpen);
|
|
$panel.toggleClass("is-open", isOpen);
|
|
$head.find(".pilar-open-cta").text(isOpen ? "Fechar Pilar ↑" : "Abrir Pilar →");
|
|
});
|
|
});
|
|
|
|
$("#pilaresContainer").on("change", ".resultado", function () {
|
|
recalc();
|
|
syncPayload();
|
|
});
|
|
|
|
$("#pilaresContainer").on("change keyup", ".justificativa", function () {
|
|
syncPayload();
|
|
});
|
|
|
|
$("#pilaresContainer").on("change", ".anexo-plugin", function () {
|
|
syncPayload();
|
|
});
|
|
|
|
$("#pilaresContainer").on("click", ".anexo-toggle", function () {
|
|
var $btn = $(this);
|
|
var expanded = $btn.attr("data-expanded") === "true";
|
|
var total = parseInt($btn.attr("data-total"), 10) || 0;
|
|
var $wrap = $btn.closest(".anexos-cell");
|
|
var $list = $wrap.find(".anexo-multi-list").first();
|
|
if (expanded) {
|
|
$list.removeClass("expanded");
|
|
$btn.attr("data-expanded", "false").text("Mostrar todas (" + total + ")");
|
|
} else {
|
|
$list.addClass("expanded");
|
|
$btn.attr("data-expanded", "true").text("Mostrar menos");
|
|
}
|
|
});
|
|
|
|
$(document).on("click", ".nc-item", function () {
|
|
var pilar = $(this).attr("data-pilar") || "";
|
|
var indicador = $(this).attr("data-indicador") || "";
|
|
var $tr = $(".audit-row[data-pilar='" + pilar.replace(/'/g, "\\'") + "'][data-indicador='" + indicador.replace(/'/g, "\\'") + "']").first();
|
|
if (!$tr.length) {
|
|
$tr = findRowByIndicador(indicador);
|
|
}
|
|
if (!$tr.length) return;
|
|
$tr.addClass("audit-row-target");
|
|
setTimeout(function () { $tr.removeClass("audit-row-target"); }, 1600);
|
|
$("html, body").animate({ scrollTop: $tr.offset().top - 120 }, 250);
|
|
});
|
|
|
|
hideNativeSendButtons();
|
|
setTimeout(hideNativeSendButtons, 600);
|
|
|
|
$("#btnEnviarForm").on("click", function () {
|
|
if (!validarFormulario()) return;
|
|
var clicked = clickNativeSendButton();
|
|
if (!clicked) {
|
|
FLUIGC.toast({
|
|
title: "Envio:",
|
|
message: "Nao foi possivel acionar o botao nativo de Enviar.",
|
|
type: "warning"
|
|
});
|
|
}
|
|
});
|
|
|
|
window.beforeSendValidate = function () {
|
|
return validarFormulario();
|
|
};
|
|
});
|