Primeira versão do diagnóstico
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
$pdo = new PDO(
|
||||
'mysql:host=127.0.0.1;dbname=diagnosticoempresas;charset=utf8mb4',
|
||||
'root',
|
||||
''
|
||||
);
|
||||
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
try {
|
||||
require __DIR__ . '/db.php';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['ok' => false, 'erro' => 'Metodo nao permitido']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$payload = json_decode(file_get_contents('php://input'), true);
|
||||
if (!is_array($payload) || !isset($payload['respostas'], $payload['resultado'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['ok' => false, 'erro' => 'Dados invalidos']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->exec(
|
||||
'CREATE TABLE IF NOT EXISTS diagnosticos (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
nome VARCHAR(150) NULL,
|
||||
empresa VARCHAR(200) NULL,
|
||||
email VARCHAR(255) NULL,
|
||||
telefone VARCHAR(40) NULL,
|
||||
consent_contact TINYINT(1) NOT NULL DEFAULT 0,
|
||||
consent_privacy TINYINT(1) NOT NULL DEFAULT 0,
|
||||
respostas_json LONGTEXT NOT NULL,
|
||||
resultado_json LONGTEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci'
|
||||
);
|
||||
|
||||
$answers = $payload['respostas'];
|
||||
$result = $payload['resultado'];
|
||||
$toJson = static function ($value) {
|
||||
return json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
|
||||
};
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
'INSERT INTO diagnosticos
|
||||
(nome, empresa, email, telefone, consent_contact, consent_privacy, respostas_json, resultado_json)
|
||||
VALUES
|
||||
(:nome, :empresa, :email, :telefone, :consent_contact, :consent_privacy, :respostas_json, :resultado_json)'
|
||||
);
|
||||
$stmt->execute([
|
||||
':nome' => $answers['leadNome'] ?? null,
|
||||
':empresa' => $answers['leadEmpresa'] ?? null,
|
||||
':email' => $answers['leadEmail'] ?? null,
|
||||
':telefone' => $answers['leadTel'] ?? null,
|
||||
':consent_contact' => !empty($answers['consentContact']) ? 1 : 0,
|
||||
':consent_privacy' => !empty($answers['consentPrivacy']) ? 1 : 0,
|
||||
':respostas_json' => $toJson($answers),
|
||||
':resultado_json' => $toJson($result),
|
||||
]);
|
||||
|
||||
echo json_encode(['ok' => true, 'id' => $pdo->lastInsertId()]);
|
||||
} catch (Throwable $error) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['ok' => false, 'erro' => 'Nao foi possivel guardar o diagnostico']);
|
||||
}
|
||||
@@ -0,0 +1,828 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="pt-PT">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Diagnóstico Digital PME</title>
|
||||
<style>
|
||||
:root{
|
||||
--navy:#12203b;
|
||||
--navy-2:#1b2f52;
|
||||
--blue:#2f6fed;
|
||||
--blue-light:#eaf1ff;
|
||||
--green:#1f9d6b;
|
||||
--amber:#e0972f;
|
||||
--red:#d64545;
|
||||
--ink:#1a2233;
|
||||
--muted:#5b6579;
|
||||
--line:#e4e8f0;
|
||||
--bg:#f6f8fc;
|
||||
--card:#ffffff;
|
||||
--radius:14px;
|
||||
font-size:16px;
|
||||
}
|
||||
*{box-sizing:border-box;}
|
||||
body{
|
||||
margin:0; font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
||||
background:var(--bg); color:var(--ink); line-height:1.5;
|
||||
}
|
||||
.app{ max-width:720px; margin:0 auto; padding:28px 20px 80px; min-height:100vh; }
|
||||
.screen{ display:none; }
|
||||
.screen.active{ display:block; animation:fade .25s ease; }
|
||||
@keyframes fade{ from{opacity:0; transform:translateY(6px);} to{opacity:1; transform:translateY(0);} }
|
||||
|
||||
/* Landing */
|
||||
.hero{ background:linear-gradient(135deg,var(--navy),var(--navy-2)); color:#fff; border-radius:var(--radius); padding:40px 30px; margin-bottom:20px;}
|
||||
.hero h1{ font-size:28px; margin:0 0 14px; line-height:1.25;}
|
||||
.hero p{ font-size:15.5px; color:#dbe4f7; margin:0 0 10px;}
|
||||
.badge-row{ display:flex; flex-wrap:wrap; gap:8px; margin:18px 0 22px;}
|
||||
.pill{ background:rgba(255,255,255,.12); border:1px solid rgba(255,255,255,.25); color:#fff; font-size:12.5px; padding:6px 12px; border-radius:20px;}
|
||||
.cta{
|
||||
display:inline-block; background:var(--blue); color:#fff; font-weight:600; font-size:16px;
|
||||
padding:14px 26px; border-radius:10px; border:none; cursor:pointer; box-shadow:0 6px 16px rgba(47,111,237,.35);
|
||||
}
|
||||
.cta:hover{ background:#255fd6; }
|
||||
.cta.secondary{ background:transparent; color:var(--blue); box-shadow:none; border:1.5px solid var(--blue); }
|
||||
.meta-note{ font-size:13px; color:var(--muted); margin-top:14px;}
|
||||
.stat-mini{ font-size:13px; color:#cfe0ff;}
|
||||
|
||||
/* Form */
|
||||
.progress-wrap{ margin-bottom:22px;}
|
||||
.progress-track{ height:8px; background:var(--line); border-radius:8px; overflow:hidden;}
|
||||
.progress-fill{ height:100%; background:var(--blue); border-radius:8px; transition:width .3s ease;}
|
||||
.progress-label{ display:flex; justify-content:space-between; font-size:12.5px; color:var(--muted); margin-top:6px;}
|
||||
.card{ background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:26px 24px; box-shadow:0 2px 10px rgba(20,30,60,.04);}
|
||||
.q-part{ font-size:12.5px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--blue); margin:0 0 8px;}
|
||||
.q-text{ font-size:19px; font-weight:600; margin:0 0 16px; color:var(--ink);}
|
||||
.q-hint{ font-size:13px; color:var(--muted); margin:-8px 0 16px;}
|
||||
.options{ display:flex; flex-direction:column; gap:10px;}
|
||||
.option{
|
||||
display:flex; align-items:center; gap:12px; border:1.5px solid var(--line); border-radius:10px;
|
||||
padding:13px 16px; cursor:pointer; font-size:15px; transition:border-color .15s, background .15s;
|
||||
}
|
||||
.option:hover{ border-color:#b9c9f2; background:#fafbff;}
|
||||
.option.selected{ border-color:var(--blue); background:var(--blue-light); font-weight:600;}
|
||||
.option input{ accent-color:var(--blue); width:17px; height:17px; flex-shrink:0;}
|
||||
textarea, input[type=text], input[type=email], input[type=tel]{
|
||||
width:100%; border:1.5px solid var(--line); border-radius:10px; padding:12px 14px; font-size:15px; font-family:inherit; resize:vertical;
|
||||
}
|
||||
textarea:focus, input:focus{ outline:none; border-color:var(--blue);}
|
||||
.nav-row{ display:flex; justify-content:space-between; align-items:center; margin-top:22px;}
|
||||
.btn{ padding:12px 20px; border-radius:9px; font-weight:600; font-size:14.5px; cursor:pointer; border:1.5px solid var(--line); background:#fff; color:var(--ink);}
|
||||
.btn.primary{ background:var(--blue); border-color:var(--blue); color:#fff;}
|
||||
.btn.primary:disabled{ opacity:.4; cursor:not-allowed;}
|
||||
.btn:hover:not(:disabled){ filter:brightness(0.97);}
|
||||
.skip-link{ text-align:center; margin-top:14px;}
|
||||
.skip-link a{ color:var(--muted); font-size:13px; cursor:pointer; text-decoration:underline;}
|
||||
|
||||
/* Results */
|
||||
.result-header{ text-align:center; padding:10px 0 22px;}
|
||||
.score-big{ font-size:52px; font-weight:800; color:var(--navy); margin:6px 0 2px;}
|
||||
.score-sub{ color:var(--muted); font-size:14px;}
|
||||
.profile-tag{ display:inline-block; margin-top:14px; font-size:15px; font-weight:700; padding:8px 18px; border-radius:30px; }
|
||||
.tag-green{ background:#e6f6ee; color:var(--green);}
|
||||
.tag-amber{ background:#fdf0dd; color:var(--amber);}
|
||||
.tag-red{ background:#fbe9e9; color:var(--red);}
|
||||
.profile-desc{ color:var(--muted); font-size:14.5px; max-width:520px; margin:12px auto 0;}
|
||||
.section-title{ font-size:15px; font-weight:700; margin:30px 0 14px; color:var(--ink);}
|
||||
.indicator{ margin-bottom:14px;}
|
||||
.indicator-top{ display:flex; justify-content:space-between; font-size:14px; margin-bottom:6px;}
|
||||
.indicator-top .name{ font-weight:600;}
|
||||
.indicator-track{ height:10px; background:var(--line); border-radius:8px; overflow:hidden;}
|
||||
.indicator-fill{ height:100%; border-radius:8px;}
|
||||
.opportunity-card{ background:var(--blue-light); border-radius:var(--radius); padding:22px; margin-top:10px;}
|
||||
.opportunity-card h3{ margin:0 0 8px; font-size:17px;}
|
||||
.opportunity-card p{ margin:0 0 14px; font-size:14.5px; color:#33456e;}
|
||||
.opportunity-card ol{ margin:0; padding-left:20px; font-size:14.5px; color:#33456e;}
|
||||
.opportunity-card ol li{ margin-bottom:6px;}
|
||||
.priority-item{ display:flex; gap:14px; align-items:flex-start; padding:14px 0; border-bottom:1px solid var(--line);}
|
||||
.priority-item:last-child{ border-bottom:none;}
|
||||
.priority-num{ font-size:22px; font-weight:800; color:#c7d2ea; width:34px; flex-shrink:0;}
|
||||
.priority-title{ font-weight:600; font-size:15px;}
|
||||
.priority-potential{ font-size:13px; color:var(--muted); margin-top:2px;}
|
||||
.cta-box{ text-align:center; background:var(--navy); color:#fff; border-radius:var(--radius); padding:28px 22px; margin-top:32px;}
|
||||
.cta-box h3{ margin:0 0 10px; font-size:18px;}
|
||||
.cta-box p{ font-size:14px; color:#c9d5ee; margin:0 0 18px;}
|
||||
.lead-fields{ margin-top:16px; display:none;}
|
||||
.lead-fields.show{ display:block;}
|
||||
.field-row{ margin-bottom:12px;}
|
||||
.field-row label{ display:block; font-size:13px; font-weight:600; margin-bottom:5px;}
|
||||
.checkbox-row{ display:flex; gap:10px; align-items:flex-start; font-size:13px; color:var(--muted); margin-top:10px;}
|
||||
.checkbox-row input{ margin-top:2px;}
|
||||
.verify-toggle{ text-align:center; margin-top:26px;}
|
||||
.verify-toggle a{ font-size:12.5px; color:var(--muted); cursor:pointer; text-decoration:underline;}
|
||||
.verify-panel{ display:none; background:#0f1830; color:#cfe0ff; border-radius:12px; padding:18px; margin-top:14px; font-family:ui-monospace,Menlo,Consolas,monospace; font-size:12.5px; white-space:pre-wrap; line-height:1.6;}
|
||||
.verify-panel.show{ display:block;}
|
||||
.footer-note{ text-align:center; color:var(--muted); font-size:12px; margin-top:40px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
|
||||
<!-- LANDING -->
|
||||
<div class="screen active" id="screen-landing">
|
||||
<div class="hero">
|
||||
<h1>Descubra o potencial digital da sua empresa</h1>
|
||||
<p>Em 5–7 minutos, descubra onde a sua empresa pode reduzir trabalho manual, utilizar melhor a tecnologia, reforçar a segurança e encontrar novas oportunidades de crescimento.</p>
|
||||
<p>Este diagnóstico foi desenvolvido para pequenas e médias empresas e analisa cinco áreas: Automação, Inteligência Artificial, Sistemas e Dados, Segurança e Presença Digital & Vendas.</p>
|
||||
<p>No final receberá uma avaliação personalizada e poderá identificar as áreas que devem ser prioritárias nos próximos 12–24 meses.</p>
|
||||
<div class="badge-row">
|
||||
<span class="pill">⏱️ 5–7 minutos</span>
|
||||
<span class="pill">❓ 35 perguntas</span>
|
||||
<span class="pill">📊 Índice + 5 áreas + prioridades</span>
|
||||
</div>
|
||||
<button class="cta" onclick="startDiagnostic()">Começar diagnóstico</button>
|
||||
<div class="meta-note" style="color:#cfe0ff;">As respostas são utilizadas para gerar o diagnóstico. Os dados de contacto são opcionais, salvo se pretender receber o relatório ou ser contactado.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FORM -->
|
||||
<div class="screen" id="screen-form">
|
||||
<div class="progress-wrap">
|
||||
<div class="progress-track"><div class="progress-fill" id="progress-fill"></div></div>
|
||||
<div class="progress-label"><span id="progress-text"></span><span id="progress-pct"></span></div>
|
||||
</div>
|
||||
<div class="card" id="question-card"></div>
|
||||
<div class="nav-row">
|
||||
<button class="btn" id="btn-back" onclick="goBack()">← Anterior</button>
|
||||
<button class="btn primary" id="btn-next" onclick="goNext()">Seguinte →</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RESULTS -->
|
||||
<div class="screen" id="screen-results">
|
||||
<div id="results-content"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
/* =========================================================
|
||||
1. DADOS DAS PERGUNTAS
|
||||
========================================================= */
|
||||
const PART_NAMES = {
|
||||
1:'A sua empresa', 2:'Processos e Automação', 3:'Inteligência Artificial',
|
||||
4:'Sistemas e Dados', 5:'Segurança', 6:'Presença Digital e Vendas', 7:'Futuro'
|
||||
};
|
||||
|
||||
const QUESTIONS = [
|
||||
{id:1, part:1, type:'single', text:'Em que setor atua a sua empresa?', options:['Agricultura / Agroalimentar','Comércio','Turismo / Hotelaria / Restauração','Indústria','Construção','Transportes / Logística','Serviços profissionais','Saúde / Bem-estar','Educação / Formação','Tecnologia / Informática','Outro']},
|
||||
{id:2, part:1, type:'single', text:'Quantas pessoas trabalham atualmente na empresa?', options:['Apenas eu','2–5','6–10','11–20','21–50','Mais de 50']},
|
||||
{id:3, part:1, type:'single', text:'Qual é o principal mercado da empresa?', options:['Local','Regional','Nacional','Portugal e Espanha','Internacional']},
|
||||
{id:4, part:1, type:'single', text:'Como caracteriza atualmente a evolução do negócio?', options:['Em crescimento','Estável','Crescimento rápido','Em redução','Não sei avaliar']},
|
||||
|
||||
{id:5, part:2, type:'single', text:'Quantas tarefas administrativas da empresa dependem atualmente de Excel, Word ou email?', options:['Muito poucas','Algumas','Muitas','Uma parte significativa do trabalho'], scores:[0,5,10,15]},
|
||||
{id:6, part:2, type:'single', text:'A sua equipa precisa de introduzir os mesmos dados em diferentes sistemas?', options:['Nunca','Raramente','Algumas vezes','Frequentemente','Diariamente'], scores:[0,4,8,12,15]},
|
||||
{id:7, part:2, type:'single', text:'Existem tarefas repetitivas que consomem várias horas da equipa todas as semanas?', options:['Não','Poucas','Algumas','Muitas','São uma parte significativa do trabalho'], scores:[0,4,8,12,15]},
|
||||
{id:8, part:2, type:'single', text:'Como são tratados os pedidos recebidos de clientes?', options:['Totalmente manual','Email/formulário, seguido de tratamento manual','Temos alguns processos automatizados','Grande parte é automatizada','Processo praticamente automático'], scores:[15,12,8,3,0]},
|
||||
{id:9, part:2, type:'single', text:'Como são preparados os orçamentos/propostas?', options:['Manualmente de raiz','Utilizamos modelos, mas editamos manualmente','Temos alguma automatização','Processo bastante automatizado','Totalmente integrado com outros sistemas','Não aplicável'], scores:[15,12,7,3,0,0]},
|
||||
{id:10, part:2, type:'text', text:'Se pudesse eliminar amanhã uma tarefa repetitiva da empresa, qual seria?', hint:'Descreva brevemente essa tarefa. Esta resposta não pontua — ajuda-nos a identificar problemas reais.'},
|
||||
|
||||
{id:11, part:3, type:'single', text:'A sua empresa utiliza atualmente ferramentas de Inteligência Artificial?', options:['Não utilizamos','Alguns colaboradores experimentam ocasionalmente','Utilizamos em algumas tarefas','Utilizamos regularmente','A IA já está integrada em processos da empresa'], scores:[0,5,10,15,20]},
|
||||
{id:12, part:3, type:'multi', text:'Para que utilizam IA atualmente?', hint:'Pode selecionar várias.', options:['Criação/revisão de textos','Emails','Marketing','Atendimento ao cliente','Análise de documentos','Análise de dados','Programação','Tradução','Vendas','Apoio administrativo','Outro'], visibleIf:(a)=> a[11]!==undefined && a[11]!==0},
|
||||
{id:13, part:3, type:'single', text:'A empresa já identificou tarefas ou processos onde a IA poderia ser útil?', options:['Não fazemos ideia','Temos algumas ideias','Já identificámos várias oportunidades','Estamos a testar algumas soluções','Temos uma estratégia definida'], scores:[0,5,10,15,20]},
|
||||
{id:14, part:3, type:'single', text:'Qual seria o principal benefício que gostaria de obter através da IA?', options:['Poupar tempo','Reduzir custos','Automatizar tarefas','Melhorar o atendimento','Aumentar vendas','Melhorar análise de informação','Apoiar os colaboradores','Ainda não sabemos']},
|
||||
{id:15, part:3, type:'single', text:'Qual destas afirmações melhor descreve a empresa?', options:['Temos interesse em IA mas não sabemos por onde começar.','Experimentámos algumas ferramentas.','Já utilizamos IA em algumas tarefas.','Queremos integrar IA nos nossos processos.','Já temos uma estratégia de IA.'], scores:[20,15,10,5,0]},
|
||||
|
||||
{id:16, part:4, type:'multi', text:'Que tipo de software utiliza atualmente?', hint:'Pode selecionar vários.', options:['Software de faturação','ERP / Gestão','CRM','Gestão de stocks','Gestão de projetos','Recursos humanos','Reservas','E-commerce','Outro','Nenhum']},
|
||||
{id:17, part:4, type:'single', text:'Os diferentes sistemas utilizados pela empresa comunicam entre si?', options:['Não','Muito pouco','Alguns estão integrados','A maioria está integrada','Os sistemas estão bem integrados'], scores:[15,12,7,3,0], visibleIf:(a)=>{ const sel=a[16]||[]; const onlyNone = sel.length===0 || (sel.length===1 && sel[0]===9); return !onlyNone; }},
|
||||
{id:18, part:4, type:'single', text:'Onde estão armazenados os principais documentos e dados da empresa?', options:['Principalmente em papel','Computadores individuais','Servidores locais','Cloud','Cloud + sistemas centralizados'], scores:[0,4,7,12,15]},
|
||||
{id:19, part:4, type:'single', text:'A direção consegue consultar facilmente os principais indicadores do negócio?', options:['Não','Temos de preparar informação manualmente','Temos alguns indicadores','Temos dashboards','Temos informação atualizada automaticamente'], scores:[0,5,10,15,20]},
|
||||
{id:20, part:4, type:'single', text:'Quantas folhas Excel são críticas para o funcionamento da empresa?', options:['Nenhuma','1–2','3–5','Mais de 5','Temos processos críticos que dependem fortemente de Excel'], scores:[0,3,7,12,15]},
|
||||
|
||||
{id:21, part:5, type:'single', text:'A autenticação multifator (MFA) está ativa nas contas importantes?', options:['Não','Apenas algumas','Na maioria','Em todas as contas relevantes','Não sei'], scores:[15,10,5,0,15]},
|
||||
{id:22, part:5, type:'single', text:'Os dados importantes da empresa têm backups automáticos?', options:['Não','Não sabemos','Sim, mas não fazemos testes regularmente','Sim, com testes regulares'], scores:[15,12,5,0]},
|
||||
{id:23, part:5, type:'single', text:'Se amanhã perdessem todos os computadores da empresa, quanto tempo demorariam a recuperar?', options:['Não sabemos','Várias semanas','Vários dias','Menos de 24 horas','Temos um plano de recuperação testado'], scores:[15,12,7,3,0]},
|
||||
{id:24, part:5, type:'single', text:'A equipa recebe formação sobre phishing e segurança digital?', options:['Nunca','Raramente','Algumas vezes por ano','Regularmente'], scores:[10,7,3,0]},
|
||||
{id:25, part:5, type:'single', text:'Quem é responsável pela segurança informática da empresa?', options:['Ninguém','Um colaborador acumula essa função','Técnico/empresa externa','Responsável interno + apoio especializado'], scores:[10,6,3,0]},
|
||||
|
||||
{id:26, part:6, type:'single', text:'Como avalia atualmente o website da empresa?', options:['Não temos website','Temos, mas está bastante desatualizado','Funciona mas precisa de melhorias','Está atualizado e profissional','É uma ferramenta ativa de vendas'], scores:[15,12,7,3,0]},
|
||||
{id:27, part:6, type:'single', text:'A empresa vende produtos ou serviços através da Internet?', options:['Não','Não, mas temos interesse','Temos presença online, mas não vendemos','Temos loja online','A venda online é um canal importante'], scores:[10,8,5,2,0]},
|
||||
{id:28, part:6, type:'single', text:'Conseguem saber quantas pessoas visitam o website e quantas se transformam em contactos/clientes?', options:['Não','Temos algumas métricas','Sim, mas analisamos manualmente','Sim, acompanhamos regularmente','Sim, temos acompanhamento integrado'], scores:[15,10,7,3,0], visibleIf:(a)=> a[26]!==undefined && a[26]!==0},
|
||||
{id:29, part:6, type:'multi', text:'Quais são atualmente os principais canais de aquisição de clientes?', hint:'Escolha vários.', options:['Recomendação','Google','Website','Redes sociais','Publicidade online','Email','Prospeção comercial','Marketplace','Parceiros','Outro']},
|
||||
{id:30, part:6, type:'single', text:'Sabem quanto custa, aproximadamente, adquirir um novo cliente?', options:['Não','Temos uma estimativa','Sim','Sim, por canal','Sim, de forma automática'], scores:[10,7,4,2,0]},
|
||||
|
||||
{id:31, part:7, type:'multi', max:3, text:'Quais destas áreas serão prioritárias para a empresa nos próximos 24 meses?', hint:'Escolha até 3. (Esta pergunta não entra no índice — é para investigação de mercado.)', options:['Inteligência Artificial','Automação','Cibersegurança','Integração de sistemas','Software de gestão','E-commerce','Website','Marketing digital','Dados / Business Intelligence','Cloud','Outro']},
|
||||
{id:32, part:7, type:'single', text:'Qual é atualmente o maior obstáculo à digitalização?', options:['Falta de orçamento','Falta de conhecimento','Falta de tempo','Não sabemos por onde começar','Sistemas demasiado antigos','Sistemas que não comunicam entre si','Falta de recursos humanos','Resistência interna','Não sabemos se o investimento terá retorno','Outro']},
|
||||
{id:33, part:7, type:'single', text:'Imagine que uma solução tecnológica conseguia poupar 20 horas de trabalho por mês. Qual seria o nível de investimento que consideraria razoável?', options:['Menos de 500 €','500–1.500 €','1.500–3.000 €','3.000–5.000 €','5.000–10.000 €','Mais de 10.000 €, dependendo do retorno','Não sei']},
|
||||
{id:34, part:7, type:'text', text:'Qual é o principal problema tecnológico ou operacional que gostaria de resolver nos próximos 12 meses?', hint:'Seja tão específico quanto possível. Ex.: "Perdemos muito tempo a preparar orçamentos", "temos informação duplicada em três sistemas".'},
|
||||
{id:35, part:7, type:'single', text:'Quer receber o seu diagnóstico detalhado?', options:['Sim, quero receber o relatório','Não, quero apenas consultar o resultado']},
|
||||
];
|
||||
|
||||
const SCORES = {};
|
||||
QUESTIONS.forEach(q=>{ if(q.scores) SCORES[q.id]=q.scores; });
|
||||
|
||||
/* =========================================================
|
||||
1.1 BENCHMARK SETORIAL (fonte: INE, IUTICE 2025)
|
||||
Fonte: INE, I.P. — Inquérito à Utilização de Tecnologias da Informação
|
||||
e da Comunicação nas Empresas (IUTICE), edição de 21/11/2025.
|
||||
Universo do inquérito: empresas com 10 ou mais pessoas ao serviço
|
||||
(não inclui microempresas nem trabalhadores independentes).
|
||||
Os valores por área são uma ESTIMATIVA aproximada, construída a partir
|
||||
de indicadores INE que se aproximam de cada área do diagnóstico — não
|
||||
resultam da mesma metodologia/perguntas do diagnóstico, pelo que servem
|
||||
como referência de mercado, não como comparação exata:
|
||||
- Automação ≈ média (% software empresarial, % com ERP)
|
||||
- IA = % empresas que utilizam tecnologias de IA
|
||||
- Sistemas ≈ média (% software empresarial, % cloud, % análise de dados)
|
||||
- Segurança ≈ média (% com ≥1 medida de segurança TIC, 100-% com incidentes) [dados 2024]
|
||||
- Digital ≈ média (% com website, % com redes sociais/social media, % com comércio eletrónico)
|
||||
"Outros serviços" agrega Serviços profissionais, Saúde e Educação (o INE
|
||||
não os reporta em separado). Não há segmento próprio para Agricultura —
|
||||
usa-se a média nacional. ver Roadmap para detalhe e limitações.
|
||||
========================================================= */
|
||||
const BENCHMARK = {
|
||||
nacional: { label:'Média nacional (todos os setores)', automacao:51, ia:12, sistemas:46, seguranca:91, digital:50 },
|
||||
industria_energia: { label:'Indústria e energia', automacao:58, ia:10, sistemas:47, seguranca:91, digital:45 },
|
||||
construcao_imobiliarias: { label:'Construção e atividades imobiliárias', automacao:31, ia:6, sistemas:30, seguranca:96, digital:37 },
|
||||
comercio: { label:'Comércio', automacao:57, ia:9, sistemas:51, seguranca:91, digital:58 },
|
||||
transportes_armazenagem: { label:'Transportes e armazenagem', automacao:56, ia:15, sistemas:57, seguranca:92, digital:45 },
|
||||
alojamento_restauracao: { label:'Alojamento e restauração (Turismo/Hotelaria)', automacao:38, ia:8, sistemas:35, seguranca:88, digital:52 },
|
||||
informacao_comunicacao: { label:'Informação e comunicação (Tecnologia)', automacao:71, ia:53, sistemas:73, seguranca:92, digital:69 },
|
||||
outros_servicos: { label:'Outros serviços (Serv. profissionais, Saúde, Educação)', automacao:61, ia:19, sistemas:56, seguranca:91, digital:53 },
|
||||
};
|
||||
// Q1 (setor) index -> chave do BENCHMARK
|
||||
const SECTOR_BENCHMARK_MAP = {
|
||||
0:'nacional', // Agricultura / Agroalimentar (sem segmento próprio no INE)
|
||||
1:'comercio', // Comércio
|
||||
2:'alojamento_restauracao', // Turismo / Hotelaria / Restauração
|
||||
3:'industria_energia', // Indústria
|
||||
4:'construcao_imobiliarias', // Construção
|
||||
5:'transportes_armazenagem', // Transportes / Logística
|
||||
6:'outros_servicos', // Serviços profissionais
|
||||
7:'outros_servicos', // Saúde / Bem-estar
|
||||
8:'outros_servicos', // Educação / Formação
|
||||
9:'informacao_comunicacao', // Tecnologia / Informática
|
||||
10:'nacional', // Outro
|
||||
};
|
||||
|
||||
/* =========================================================
|
||||
2. ESTADO
|
||||
========================================================= */
|
||||
let answers = {}; // { qid: index | [indexes] | "texto" }
|
||||
let currentIdx = 0; // índice no array QUESTIONS
|
||||
|
||||
function isVisible(q){
|
||||
if (q.visibleIf) return q.visibleIf(answers);
|
||||
return true;
|
||||
}
|
||||
|
||||
function firstVisibleFrom(idx, dir){
|
||||
let i = idx;
|
||||
while (i>=0 && i<QUESTIONS.length && !isVisible(QUESTIONS[i])) i += dir;
|
||||
return i;
|
||||
}
|
||||
|
||||
function visibleCountTotal(){
|
||||
return QUESTIONS.filter(isVisible).length;
|
||||
}
|
||||
function visiblePositionOf(idx){
|
||||
let pos=0;
|
||||
for(let i=0;i<=idx;i++){ if(isVisible(QUESTIONS[i])) pos++; }
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
3. NAVEGAÇÃO / RENDER DO FORMULÁRIO
|
||||
========================================================= */
|
||||
function startDiagnostic(){
|
||||
document.getElementById('screen-landing').classList.remove('active');
|
||||
document.getElementById('screen-form').classList.add('active');
|
||||
currentIdx = firstVisibleFrom(0,1);
|
||||
renderQuestion();
|
||||
}
|
||||
|
||||
function renderQuestion(){
|
||||
const q = QUESTIONS[currentIdx];
|
||||
const card = document.getElementById('question-card');
|
||||
let html = `<div class="q-part">Parte ${q.part} — ${PART_NAMES[q.part]}</div>`;
|
||||
html += `<div class="q-text">${q.id}. ${q.text}</div>`;
|
||||
if(q.hint) html += `<div class="q-hint">${q.hint}</div>`;
|
||||
|
||||
if(q.type==='single'){
|
||||
html += '<div class="options">';
|
||||
q.options.forEach((opt,i)=>{
|
||||
const sel = answers[q.id]===i ? 'selected' : '';
|
||||
html += `<label class="option ${sel}" onclick="selectSingle(${q.id},${i})">
|
||||
<input type="radio" name="q${q.id}" ${answers[q.id]===i?'checked':''}> <span>${opt}</span>
|
||||
</label>`;
|
||||
});
|
||||
html += '</div>';
|
||||
} else if(q.type==='multi'){
|
||||
html += '<div class="options">';
|
||||
const arr = answers[q.id] || [];
|
||||
q.options.forEach((opt,i)=>{
|
||||
const sel = arr.includes(i) ? 'selected' : '';
|
||||
html += `<label class="option ${sel}" onclick="selectMulti(${q.id},${i},${q.max||0})">
|
||||
<input type="checkbox" ${arr.includes(i)?'checked':''}> <span>${opt}</span>
|
||||
</label>`;
|
||||
});
|
||||
html += '</div>';
|
||||
} else if(q.type==='text'){
|
||||
const val = answers[q.id] || '';
|
||||
html += `<textarea rows="4" placeholder="Escreva aqui a sua resposta..." oninput="answers[${q.id}]=this.value; updateNextButton();">${val}</textarea>`;
|
||||
}
|
||||
|
||||
// Campos extra da pergunta 35 (lead)
|
||||
if(q.id===35){
|
||||
const showLead = answers[35]===0;
|
||||
html += `<div class="lead-fields ${showLead?'show':''}" id="lead-fields">
|
||||
<div class="field-row"><label>Nome</label><input type="text" id="lead-nome" value="${escapeHtml(answers.leadNome||'')}" oninput="answers.leadNome=this.value"></div>
|
||||
<div class="field-row"><label>Empresa</label><input type="text" id="lead-empresa" value="${escapeHtml(answers.leadEmpresa||'')}" oninput="answers.leadEmpresa=this.value"></div>
|
||||
<div class="field-row"><label>Email</label><input type="email" id="lead-email" value="${escapeHtml(answers.leadEmail||'')}" oninput="answers.leadEmail=this.value"></div>
|
||||
<div class="field-row"><label>Telefone (opcional)</label><input type="tel" id="lead-tel" value="${escapeHtml(answers.leadTel||'')}" oninput="answers.leadTel=this.value"></div>
|
||||
<div class="checkbox-row"><input type="checkbox" id="consent-contact" ${answers.consentContact?'checked':''} onchange="answers.consentContact=this.checked"> <label for="consent-contact">Aceito ser contactado pela TECH X relativamente ao resultado deste diagnóstico e a soluções que possam ser relevantes para a minha empresa.</label></div>
|
||||
<div class="checkbox-row"><input type="checkbox" id="consent-privacy" ${answers.consentPrivacy?'checked':''} onchange="answers.consentPrivacy=this.checked"> <label for="consent-privacy">Li e aceito a política de privacidade e o tratamento dos meus dados.</label></div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
card.innerHTML = html;
|
||||
updateProgress();
|
||||
updateNextButton();
|
||||
document.getElementById('btn-back').disabled = (currentIdx===firstVisibleFrom(0,1));
|
||||
}
|
||||
|
||||
function selectSingle(qid, idx){
|
||||
answers[qid]=idx;
|
||||
if(qid===35){ /* re-render to show/hide lead fields */ }
|
||||
renderQuestion();
|
||||
}
|
||||
function selectMulti(qid, idx, max){
|
||||
let arr = answers[qid] || [];
|
||||
if(arr.includes(idx)){
|
||||
arr = arr.filter(x=>x!==idx);
|
||||
} else {
|
||||
if(max && arr.length>=max){ return; }
|
||||
arr = qid===16 && idx===9 ? [9] : [...arr.filter(x=>!(qid===16 && x===9)), idx];
|
||||
}
|
||||
answers[qid]=arr;
|
||||
renderQuestion();
|
||||
}
|
||||
|
||||
function isAnswered(q){
|
||||
if(q.type==='text') return true; // resposta aberta é opcional
|
||||
if(q.type==='multi') return true; // seleção múltipla é opcional
|
||||
return answers[q.id]!==undefined;
|
||||
}
|
||||
|
||||
function updateNextButton(){
|
||||
const q = QUESTIONS[currentIdx];
|
||||
const btn = document.getElementById('btn-next');
|
||||
btn.disabled = !isAnswered(q);
|
||||
const isLast = firstVisibleFrom(currentIdx+1,1) >= QUESTIONS.length;
|
||||
btn.textContent = isLast ? 'Ver resultado →' : 'Seguinte →';
|
||||
}
|
||||
|
||||
function updateProgress(){
|
||||
const total = visibleCountTotal();
|
||||
const pos = visiblePositionOf(currentIdx);
|
||||
document.getElementById('progress-fill').style.width = (pos/total*100)+'%';
|
||||
document.getElementById('progress-text').textContent = `Pergunta ${pos} de ${total}`;
|
||||
document.getElementById('progress-pct').textContent = Math.round(pos/total*100)+'%';
|
||||
}
|
||||
|
||||
function escapeHtml(value){
|
||||
return String(value).replace(/[&<>"']/g, char=>({
|
||||
'&':'&', '<':'<', '>':'>', '"':'"', "'":'''
|
||||
}[char]));
|
||||
}
|
||||
|
||||
function goNext(){
|
||||
const nextIdx = firstVisibleFrom(currentIdx+1,1);
|
||||
if(nextIdx>=QUESTIONS.length){
|
||||
showResults();
|
||||
return;
|
||||
}
|
||||
currentIdx = nextIdx;
|
||||
renderQuestion();
|
||||
}
|
||||
function goBack(){
|
||||
const prevIdx = firstVisibleFrom(currentIdx-1,-1);
|
||||
if(prevIdx<0) return;
|
||||
currentIdx = prevIdx;
|
||||
renderQuestion();
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
4. MOTOR DE SCORING
|
||||
========================================================= */
|
||||
function avg(arr){ return arr.reduce((a,b)=>a+b,0)/arr.length; }
|
||||
|
||||
/* =========================================================
|
||||
3.1 MATRIZ GUT (Gravidade x Urgência x Tendência)
|
||||
Cada dimensão é pontuada de 1 a 5; prioridade = G x U x T (1 a 125).
|
||||
Urgência reflete APENAS a perceção da própria empresa (pergunta 31/33) —
|
||||
não sobe artificialmente por causa da gravidade calculada.
|
||||
Tendência tem um "piso" fixo mais alto em Segurança e IA, por serem
|
||||
áreas em que o risco/pressão de mercado tende a agravar-se mesmo sem
|
||||
sinal direto nas respostas da empresa.
|
||||
========================================================= */
|
||||
function to5(pct){ return Math.max(1, Math.min(5, Math.ceil((pct||0)/20))); }
|
||||
function growthFactor(q4idx){
|
||||
const map = {0:3, 1:2, 2:5, 3:2, 4:3}; // crescimento/estável/rápido/redução/não sei
|
||||
return (q4idx!==undefined && map[q4idx]!==undefined) ? map[q4idx] : 3;
|
||||
}
|
||||
// Mapa: quais opções da pergunta 31 "contam" como urgência para cada área
|
||||
const Q31_URGENCIA_MAP = {
|
||||
automacao: [1], // Automação
|
||||
ia: [0], // Inteligência Artificial
|
||||
sistemas: [3,4,8,9], // Integração de sistemas, Software de gestão, Dados/BI, Cloud
|
||||
seguranca: [2], // Cibersegurança
|
||||
digital: [5,6,7], // E-commerce, Website, Marketing digital
|
||||
};
|
||||
function urgencia(areaKey, a){
|
||||
const sel = a[31] || [];
|
||||
const relevant = Q31_URGENCIA_MAP[areaKey].some(i=>sel.includes(i));
|
||||
if(!relevant) return 1; // não foi marcada como prioridade pela própria empresa
|
||||
const q33 = a[33];
|
||||
return (q33!==undefined && q33>=2) ? 5 : 4; // reforço se disposta a investir 1.500€+
|
||||
}
|
||||
function gutLabel(score){
|
||||
if(score>=75) return 'Crítico';
|
||||
if(score>=45) return 'Alto';
|
||||
if(score>=20) return 'Médio';
|
||||
return 'Baixo';
|
||||
}
|
||||
function gutColor(label){
|
||||
if(label==='Crítico') return '#d64545';
|
||||
if(label==='Alto') return '#e0972f';
|
||||
if(label==='Médio') return '#2f6fed';
|
||||
return '#5b6579';
|
||||
}
|
||||
function computeGUT(a, areas, benchmark){
|
||||
const gut = {};
|
||||
|
||||
// AUTOMAÇÃO
|
||||
{
|
||||
const raw7 = a[7]!==undefined ? SCORES[7][a[7]] : 0;
|
||||
const g = to5(raw7/15*100);
|
||||
const u = urgencia('automacao', a);
|
||||
const t = growthFactor(a[4]);
|
||||
gut.automacao = {g,u,t,score:g*u*t};
|
||||
}
|
||||
// INTELIGÊNCIA ARTIFICIAL
|
||||
{
|
||||
const benchIA = benchmark ? benchmark.areas.ia : 12;
|
||||
const gap = Math.max(0, benchIA - areas.ia.maturidade);
|
||||
const g = to5(gap*2);
|
||||
const u = urgencia('ia', a);
|
||||
const t = (benchmark && benchmark.key==='informacao_comunicacao') ? 5 : 4; // piso fixo
|
||||
gut.ia = {g,u,t,score:g*u*t};
|
||||
}
|
||||
// SISTEMAS & DADOS
|
||||
{
|
||||
const raw20 = a[20]!==undefined ? SCORES[20][a[20]] : 0;
|
||||
const g = to5(raw20/15*100);
|
||||
const u = urgencia('sistemas', a);
|
||||
const sizeBonus = (a[2]!==undefined && a[2]>=3) ? 1 : 0;
|
||||
const t = Math.max(1, Math.min(5, growthFactor(a[4]) + sizeBonus));
|
||||
gut.sistemas = {g,u,t,score:g*u*t};
|
||||
}
|
||||
// SEGURANÇA
|
||||
{
|
||||
const raw22 = a[22]!==undefined ? SCORES[22][a[22]] : 15;
|
||||
const raw23 = a[23]!==undefined ? SCORES[23][a[23]] : 15;
|
||||
const g = to5(avg([raw22/15, raw23/15])*100);
|
||||
const u = urgencia('seguranca', a);
|
||||
const t = (a[21]===0 || a[21]===4) ? 5 : 4; // piso fixo, sobe se sem MFA / não sabe
|
||||
gut.seguranca = {g,u,t,score:g*u*t};
|
||||
}
|
||||
// DIGITAL & VENDAS
|
||||
{
|
||||
const raw30 = a[30]!==undefined ? SCORES[30][a[30]] : 0;
|
||||
const raw26 = a[26]!==undefined ? SCORES[26][a[26]] : 0;
|
||||
const g = to5(avg([raw30/10, raw26/15])*100);
|
||||
const u = urgencia('digital', a);
|
||||
const t = growthFactor(a[4]);
|
||||
gut.digital = {g,u,t,score:g*u*t};
|
||||
}
|
||||
return gut;
|
||||
}
|
||||
|
||||
function computeResults(){
|
||||
const a = answers;
|
||||
|
||||
// ---- AUTOMAÇÃO (max 15 cada) ----
|
||||
const autoRaw = [5,6,7,8,9].map(id=> a[id]!==undefined ? SCORES[id][a[id]] : null).filter(v=>v!==null);
|
||||
const autoProblemAvg = autoRaw.length ? avg(autoRaw) : 0;
|
||||
const automacao_maturidade = round(100 - (autoProblemAvg/15*100));
|
||||
const automacao_oportunidade = round(100 - automacao_maturidade);
|
||||
|
||||
// ---- IA ----
|
||||
const ia11 = a[11]!==undefined ? SCORES[11][a[11]] : 0;
|
||||
const ia13 = a[13]!==undefined ? SCORES[13][a[13]] : 0;
|
||||
const ia_maturidade = round(((ia11+ia13)/2)/20*100);
|
||||
const ia15 = a[15]!==undefined ? SCORES[15][a[15]] : 0;
|
||||
const ia_oportunidade = round(ia15/20*100);
|
||||
|
||||
// ---- SISTEMAS & DADOS ----
|
||||
const q18 = a[18]!==undefined ? SCORES[18][a[18]] : 0;
|
||||
const q19 = a[19]!==undefined ? SCORES[19][a[19]] : 0;
|
||||
const q17raw = a[17]!==undefined ? SCORES[17][a[17]] : null;
|
||||
const sistemasMatComponents = [q18/15, q19/20];
|
||||
if(q17raw!==null) sistemasMatComponents.push((15-q17raw)/15);
|
||||
const sistemas_maturidade = round(avg(sistemasMatComponents)*100);
|
||||
const q20 = a[20]!==undefined ? SCORES[20][a[20]] : 0;
|
||||
const sistemasOppComponents = [q20/15];
|
||||
if(q17raw!==null) sistemasOppComponents.push(q17raw/15);
|
||||
const sistemas_oportunidade = round(avg(sistemasOppComponents)*100);
|
||||
|
||||
// ---- SEGURANÇA ----
|
||||
const q21 = a[21]!==undefined ? SCORES[21][a[21]] : 15;
|
||||
const q22 = a[22]!==undefined ? SCORES[22][a[22]] : 15;
|
||||
const q23 = a[23]!==undefined ? SCORES[23][a[23]] : 15;
|
||||
const q24 = a[24]!==undefined ? SCORES[24][a[24]] : 10;
|
||||
const q25 = a[25]!==undefined ? SCORES[25][a[25]] : 10;
|
||||
const riskAvg = avg([q21/15, q22/15, q23/15, q24/10, q25/10]);
|
||||
const seguranca_maturidade = round(100 - riskAvg*100);
|
||||
const seguranca_oportunidade = round(riskAvg*100);
|
||||
|
||||
// ---- DIGITAL & VENDAS ----
|
||||
const q26 = a[26]!==undefined ? SCORES[26][a[26]] : 15;
|
||||
const q30 = a[30]!==undefined ? SCORES[30][a[30]] : 10;
|
||||
const q28raw = a[28]!==undefined ? SCORES[28][a[28]] : null;
|
||||
const digitalMatComponents = [(15-q26)/15, (10-q30)/10];
|
||||
if(q28raw!==null) digitalMatComponents.push((15-q28raw)/15);
|
||||
const digital_maturidade = round(avg(digitalMatComponents)*100);
|
||||
const q27 = a[27]!==undefined ? SCORES[27][a[27]] : 0;
|
||||
const digitalOppComponents = [q27/10];
|
||||
if(q28raw!==null) digitalOppComponents.push(q28raw/15);
|
||||
const digital_oportunidade = round(avg(digitalOppComponents)*100);
|
||||
|
||||
// ---- ÍNDICE GLOBAL ----
|
||||
const global = round(
|
||||
automacao_maturidade*0.25 +
|
||||
ia_maturidade*0.20 +
|
||||
sistemas_maturidade*0.20 +
|
||||
seguranca_maturidade*0.20 +
|
||||
digital_maturidade*0.15
|
||||
);
|
||||
|
||||
const areas = {
|
||||
automacao: {nome:'Automação', maturidade:automacao_maturidade, oportunidade:automacao_oportunidade},
|
||||
ia: {nome:'Inteligência Artificial', maturidade:ia_maturidade, oportunidade:ia_oportunidade},
|
||||
sistemas: {nome:'Sistemas & Dados', maturidade:sistemas_maturidade, oportunidade:sistemas_oportunidade},
|
||||
seguranca: {nome:'Segurança', maturidade:seguranca_maturidade, oportunidade:seguranca_oportunidade},
|
||||
digital: {nome:'Digital & Vendas', maturidade:digital_maturidade, oportunidade:digital_oportunidade},
|
||||
};
|
||||
|
||||
// ---- PERFIS ----
|
||||
const profiles = [];
|
||||
const sistemasSelecionados = (a[16]||[]).filter(i=>i!==9).length;
|
||||
const q17Score = q17raw!==null ? q17raw : null;
|
||||
|
||||
if(automacao_maturidade < 55){
|
||||
profiles.push({key:'automatizador', emoji:'⚙️', nome:'Automatizador', forca:automacao_oportunidade,
|
||||
msg:'A sua principal oportunidade parece estar na automatização de processos.',
|
||||
steps:['Identificar os três processos que mais tempo consomem.','Mapear os passos repetitivos.','Avaliar automação e IA.','Medir o tempo poupado.']});
|
||||
}
|
||||
if(ia_oportunidade>=60 && ia_maturidade<40){
|
||||
profiles.push({key:'explorador_ia', emoji:'🤖', nome:'Explorador de IA', forca:ia_oportunidade,
|
||||
msg:'A sua empresa demonstra interesse em IA, mas ainda existe potencial significativo para transformar esse interesse em aplicações concretas.',
|
||||
steps:['Identificar 2–3 tarefas onde a IA pode ter impacto imediato.','Experimentar ferramentas gratuitas nessas tarefas.','Formar a equipa no uso básico de IA.','Definir uma pequena aplicação-piloto com objetivos claros.']});
|
||||
}
|
||||
if(sistemasSelecionados>=3 && q17Score!==null && q17Score>=7){
|
||||
profiles.push({key:'integrador', emoji:'🔗', nome:'Integrador', forca:sistemas_oportunidade,
|
||||
msg:'A integração entre os seus sistemas poderá ser uma das áreas com maior impacto.',
|
||||
steps:['Mapear todos os sistemas usados e onde os dados se repetem.','Identificar as integrações com maior impacto.','Avaliar ferramentas de integração (nativa, iPaaS ou API).','Implementar uma integração piloto e medir o tempo poupado.']});
|
||||
}
|
||||
if(seguranca_maturidade<50){
|
||||
profiles.push({key:'protecao', emoji:'🛡️', nome:'Proteção', forca:seguranca_oportunidade,
|
||||
msg:'A continuidade e segurança da empresa devem ser uma prioridade.',
|
||||
steps:['Ativar MFA em todas as contas críticas.','Configurar backups automáticos com testes de restauro regulares.','Definir um plano simples de recuperação de desastre.','Realizar formação básica de sensibilização em phishing.']});
|
||||
}
|
||||
if(digital_maturidade<50 || (a[26]!==undefined && a[26]<=1)){
|
||||
profiles.push({key:'crescimento', emoji:'📈', nome:'Crescimento Digital', forca:digital_oportunidade,
|
||||
msg:'Existe potencial para utilizar melhor os canais digitais para gerar negócio.',
|
||||
steps:['Atualizar/profissionalizar o website.','Definir objetivos e métricas de acompanhamento (analytics).','Escolher 1–2 canais digitais prioritários para investir.','Testar uma campanha ou oferta online de baixo risco.']});
|
||||
}
|
||||
profiles.sort((x,y)=> y.forca - x.forca);
|
||||
const topProfiles = profiles.slice(0,2);
|
||||
|
||||
// ---- BENCHMARK SETORIAL ----
|
||||
const benchKey = SECTOR_BENCHMARK_MAP[a[1]] || 'nacional';
|
||||
const bench = BENCHMARK[benchKey];
|
||||
const benchmark = bench ? {
|
||||
key: benchKey, label: bench.label,
|
||||
areas: {
|
||||
automacao: bench.automacao, ia: bench.ia, sistemas: bench.sistemas,
|
||||
seguranca: bench.seguranca, digital: bench.digital
|
||||
}
|
||||
} : null;
|
||||
|
||||
// ---- MATRIZ GUT (Gravidade x Urgência x Tendência) — substitui o ranking simples de "3 prioridades" ----
|
||||
const gut = computeGUT(a, areas, benchmark);
|
||||
const areaKeys = Object.keys(areas); // mesma ordem: automacao, ia, sistemas, seguranca, digital
|
||||
const priorityList = areaKeys
|
||||
.map(key=>({ key, nome: areas[key].nome, g:gut[key].g, u:gut[key].u, t:gut[key].t, score:gut[key].score, label:gutLabel(gut[key].score) }))
|
||||
.sort((x,y)=> y.score-x.score)
|
||||
.slice(0,3);
|
||||
|
||||
return { global, areas, topProfiles, priorityList, gut, benchmark, raw:{autoRaw, ia11, ia13, ia15, q18,q19,q17raw,q20, q21,q22,q23,q24,q25, q26,q27,q28raw,q30} };
|
||||
}
|
||||
|
||||
function potencialLabel(v){
|
||||
if(v>=65) return 'Elevado';
|
||||
if(v>=40) return 'Médio/Alto';
|
||||
if(v>=20) return 'Médio';
|
||||
return 'Baixo';
|
||||
}
|
||||
function round(v){ return Math.max(0, Math.min(100, Math.round(v))); }
|
||||
|
||||
function globalBucket(score){
|
||||
if(score>=81) return {emoji:'🟢', label:'Empresa Digital Avançada', cls:'tag-green'};
|
||||
if(score>=61) return {emoji:'🟡', label:'Empresa Digitalizada', cls:'tag-amber'};
|
||||
if(score>=41) return {emoji:'🟠', label:'Empresa em Desenvolvimento Digital', cls:'tag-amber'};
|
||||
return {emoji:'🔴', label:'Início da Jornada Digital', cls:'tag-red'};
|
||||
}
|
||||
function barColor(v){
|
||||
if(v>=70) return '#1f9d6b';
|
||||
if(v>=45) return '#e0972f';
|
||||
return '#d64545';
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
5. RENDER DE RESULTADOS
|
||||
========================================================= */
|
||||
function showResults(){
|
||||
document.getElementById('screen-form').classList.remove('active');
|
||||
document.getElementById('screen-results').classList.add('active');
|
||||
const r = computeResults();
|
||||
window.__lastResult = r;
|
||||
const bucket = globalBucket(r.global);
|
||||
const top = r.topProfiles[0];
|
||||
|
||||
let html = `
|
||||
<div class="result-header">
|
||||
<div class="score-sub">O seu resultado</div>
|
||||
<div class="score-big">${r.global}/100</div>
|
||||
<span class="profile-tag ${bucket.cls}">${bucket.emoji} ${bucket.label}</span>
|
||||
<p class="profile-desc">A sua empresa foi avaliada em cinco áreas-chave: Automação, Inteligência Artificial, Sistemas & Dados, Segurança e Presença Digital & Vendas. Abaixo encontra os seus indicadores e as principais oportunidades identificadas.</p>
|
||||
</div>
|
||||
|
||||
<div class="section-title">Os seus indicadores</div>
|
||||
<div class="indicators">`;
|
||||
|
||||
Object.values(r.areas).forEach(ar=>{
|
||||
html += `<div class="indicator">
|
||||
<div class="indicator-top"><span class="name">${ar.nome}</span><span>${ar.maturidade}/100</span></div>
|
||||
<div class="indicator-track"><div class="indicator-fill" style="width:${ar.maturidade}%; background:${barColor(ar.maturidade)}"></div></div>
|
||||
</div>`;
|
||||
});
|
||||
html += `</div>`;
|
||||
|
||||
if(r.benchmark){
|
||||
html += `<div class="section-title">Como se compara com o seu setor</div>
|
||||
<div class="card" style="font-size:13px; color:var(--muted); margin-bottom:14px;">
|
||||
Comparação com <strong>${r.benchmark.label}</strong> — estimativa de mercado baseada no INE
|
||||
(Inquérito à Utilização de TIC nas Empresas, 2025; empresas com 10+ trabalhadores). Os valores de
|
||||
Automação são uma aproximação indireta (adoção de software de gestão/ERP), não uma medição direta
|
||||
de trabalho manual. Ver nota metodológica no roadmap.
|
||||
</div>
|
||||
<div class="indicators">`;
|
||||
Object.keys(r.areas).forEach(key=>{
|
||||
const ar = r.areas[key];
|
||||
const refVal = r.benchmark.areas[key];
|
||||
const delta = ar.maturidade - refVal;
|
||||
const deltaTxt = delta===0 ? '=' : (delta>0 ? '▲ +'+delta : '▼ '+delta);
|
||||
const deltaColor = delta>0 ? 'var(--green)' : (delta<0 ? 'var(--red)' : 'var(--muted)');
|
||||
html += `<div class="indicator">
|
||||
<div class="indicator-top"><span class="name">${ar.nome}</span><span>A sua empresa: ${ar.maturidade} · Setor: ${refVal} <span style="color:${deltaColor}; font-weight:700;">${deltaTxt}</span></span></div>
|
||||
<div class="indicator-track" style="position:relative;">
|
||||
<div class="indicator-fill" style="width:${ar.maturidade}%; background:${barColor(ar.maturidade)}"></div>
|
||||
<div style="position:absolute; top:-3px; left:${refVal}%; width:2px; height:16px; background:#12203b;"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
html += `</div><div style="font-size:12px; color:var(--muted); margin-top:-4px;">A barra colorida é a sua empresa; a linha escura marca a média estimada do setor.</div>`;
|
||||
}
|
||||
|
||||
if(top){
|
||||
html += `<div class="section-title">A sua principal oportunidade</div>
|
||||
<div class="opportunity-card">
|
||||
<h3>${top.emoji} ${top.nome}</h3>
|
||||
<p>${top.msg}</p>
|
||||
<div style="font-weight:600; font-size:13.5px; margin-bottom:8px;">Recomendamos começar por:</div>
|
||||
<ol>${top.steps.map(s=>`<li>${s}</li>`).join('')}</ol>
|
||||
</div>`;
|
||||
if(r.topProfiles[1]){
|
||||
const p2 = r.topProfiles[1];
|
||||
html += `<div class="opportunity-card" style="margin-top:12px; background:#f3f5fb;">
|
||||
<h3>${p2.emoji} ${p2.nome}</h3>
|
||||
<p>${p2.msg}</p>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
html += `<div class="section-title">As três prioridades identificadas (Matriz GUT)</div>
|
||||
<div class="card" style="font-size:12.5px; color:var(--muted); margin-bottom:14px;">
|
||||
G = Gravidade (impacto se nada for feito) · U = Urgência (perceção da própria empresa, com base na pergunta sobre prioridades) ·
|
||||
T = Tendência (probabilidade de agravar sem intervenção). Prioridade = G × U × T, de 1 a 125.
|
||||
</div>
|
||||
<div class="priority-list">`;
|
||||
r.priorityList.forEach((p,i)=>{
|
||||
html += `<div class="priority-item">
|
||||
<div class="priority-num">${String(i+1).padStart(2,'0')}</div>
|
||||
<div style="flex:1;">
|
||||
<div class="priority-title">${p.nome}</div>
|
||||
<div class="priority-potential">G ${p.g} · U ${p.u} · T ${p.t} → <strong>${p.score}</strong>/125 — <span style="color:${gutColor(p.label)}; font-weight:700;">${p.label}</span></div>
|
||||
</div>
|
||||
</div>`;
|
||||
});
|
||||
html += `</div>`;
|
||||
|
||||
html += `<div class="cta-box">
|
||||
<h3>Quer descobrir exatamente onde pode melhorar?</h3>
|
||||
<p>O diagnóstico identifica oportunidades, mas cada empresa tem processos diferentes. Podemos analisar consigo as principais áreas identificadas e transformar o diagnóstico num plano de ação concreto.</p>
|
||||
<button class="cta" onclick="alert('Em produção: isto ligaria a um formulário de agendamento / CRM.')">Pedir análise personalizada</button>
|
||||
</div>`;
|
||||
|
||||
if(answers[35]===0){
|
||||
html += `<div class="section-title">Os seus dados de contacto</div>
|
||||
<div class="card" style="font-size:14px;">
|
||||
<div><strong>Nome:</strong> ${escapeHtml(answers.leadNome||'—')}</div>
|
||||
<div><strong>Empresa:</strong> ${escapeHtml(answers.leadEmpresa||'—')}</div>
|
||||
<div><strong>Email:</strong> ${escapeHtml(answers.leadEmail||'—')}</div>
|
||||
<div><strong>Telefone:</strong> ${escapeHtml(answers.leadTel||'—')}</div>
|
||||
<div style="margin-top:8px; color:var(--muted);">Consentimento contacto: ${answers.consentContact?'Sim':'Não'} · Consentimento privacidade: ${answers.consentPrivacy?'Sim':'Não'}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
html += `<div style="display:flex; gap:10px; justify-content:center; margin-top:26px;">
|
||||
<button class="btn" onclick="downloadJSON()">⬇️ Exportar respostas (JSON)</button>
|
||||
<button class="btn" onclick="restart()">Refazer diagnóstico</button>
|
||||
</div>`;
|
||||
|
||||
html += `<div id="save-status" class="footer-note" style="margin-top:18px;">A guardar o diagnóstico...</div>
|
||||
<div class="verify-toggle"><a onclick="toggleVerify()">Modo verificação (ver cálculo detalhado)</a></div>
|
||||
<div class="verify-panel" id="verify-panel">${buildVerifyText(r)}</div>`;
|
||||
|
||||
html += `<div class="footer-note">Protótipo — TECH X · Diagnóstico Digital PME</div>`;
|
||||
|
||||
document.getElementById('results-content').innerHTML = html;
|
||||
saveDiagnostic(r);
|
||||
}
|
||||
|
||||
function buildVerifyText(r){
|
||||
let t = 'ÍNDICE GLOBAL: '+r.global+'/100\n\n';
|
||||
Object.entries(r.areas).forEach(([k,ar])=>{
|
||||
t += ar.nome+': maturidade='+ar.maturidade+' | oportunidade='+ar.oportunidade+'\n';
|
||||
});
|
||||
t += '\nPerfis ativados: '+r.topProfiles.map(p=>p.nome+' (força='+p.forca+')').join(', ');
|
||||
if(r.benchmark){
|
||||
t += '\n\nBenchmark setorial: '+r.benchmark.label;
|
||||
Object.keys(r.areas).forEach(k=> t += '\n '+r.areas[k].nome+': empresa='+r.areas[k].maturidade+' | setor(ref)='+r.benchmark.areas[k]);
|
||||
}
|
||||
t += '\n\nMatriz GUT (G x U x T):';
|
||||
Object.keys(r.gut).forEach(k=>{
|
||||
const g=r.gut[k];
|
||||
t += '\n '+r.areas[k].nome+': G='+g.g+' U='+g.u+' T='+g.t+' -> score='+g.score+' ('+gutLabel(g.score)+')';
|
||||
});
|
||||
t += '\n\nRespostas registadas (id:valor):\n';
|
||||
Object.keys(answers).forEach(k=>{
|
||||
if(!isNaN(k)) t += ' Q'+k+': '+JSON.stringify(answers[k])+'\n';
|
||||
});
|
||||
return t;
|
||||
}
|
||||
function toggleVerify(){
|
||||
document.getElementById('verify-panel').classList.toggle('show');
|
||||
}
|
||||
|
||||
async function saveDiagnostic(result){
|
||||
const status = document.getElementById('save-status');
|
||||
try{
|
||||
const response = await fetch('guardar.php', {
|
||||
method:'POST',
|
||||
headers:{'Content-Type':'application/json'},
|
||||
body:JSON.stringify({respostas:answers, resultado:result})
|
||||
});
|
||||
const data = await response.json();
|
||||
if(!response.ok || !data.ok) throw new Error(data.erro || 'Erro ao guardar');
|
||||
status.textContent = 'Diagnóstico guardado com sucesso.';
|
||||
status.style.color = 'var(--green)';
|
||||
}catch(error){
|
||||
status.textContent = 'Não foi possível guardar o diagnóstico.';
|
||||
status.style.color = 'var(--red)';
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
function downloadJSON(){
|
||||
const r = window.__lastResult;
|
||||
const payload = { respostas: answers, resultado: r, geradoEm: new Date().toISOString() };
|
||||
const blob = new Blob([JSON.stringify(payload,null,2)], {type:'application/json'});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url; link.download = 'diagnostico-digital-pme.json';
|
||||
document.body.appendChild(link); link.click(); link.remove();
|
||||
}
|
||||
|
||||
function restart(){
|
||||
answers = {};
|
||||
currentIdx = 0;
|
||||
document.getElementById('screen-results').classList.remove('active');
|
||||
document.getElementById('screen-landing').classList.add('active');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user