Hope: O Primeiro Impacto

Imagem
  Hope: O Primeiro Impacto Título original: Hopeu 2026 16 2 h 37 min Reproduzir trailer 1:58 482 269 Uma descoberta misteriosa é feita nos arredores de uma remota cidade portuária. Os moradores se veem em uma luta desesperada pela sobrevivência contra algo que nunca encontraram antes.

 <!DOCTYPE html>

<html lang="pt">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>HEINEKEN ON TRADE - GESTÃO</title>

    <!-- Google Fonts & FontAwesome Icons -->

    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&family=Playfair+Display:ital,wght@1,700&display=swap" rel="stylesheet">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

    

    <style>

        :root {

            --heineken-green: #00824A;

            --heineken-red: #D61A22;

            --dark-gray: #111111;

            --light-gray: rgba(244, 246, 249, 0.9);

            --white: #ffffff;

            --warning-yellow: #ffc107;

            --gold: #FFD700;

        }


        * {

            box-sizing: border-box;

            margin: 0;

            padding: 0;

            font-family: 'Roboto', sans-serif;

        }


        body {

            background: linear-gradient(rgba(5, 22, 12, 0.6), rgba(5, 22, 12, 0.8)), 

                        url('46174.jpg') no-repeat center center fixed;

            background-size: cover;

            color: #eeeeee;

            overflow-x: hidden;

            position: relative;

            padding-top: 80px; 

            min-height: 100vh;

        }


        /* CABEÇALHO */

        header {

            position: fixed;

            top: 0;

            left: 0;

            width: 100%;

            height: 70px;

            background-color: #00824A !important;

            color: #ffffff !important;

            display: flex;

            justify-content: space-between;

            align-items: center;

            padding: 0 20px;

            box-shadow: 0 4px 15px rgba(0,0,0,0.5);

            border-bottom: 3px solid var(--heineken-red);

            z-index: 9999 !important;

        }


        .header-title {

            display: flex;

            align-items: center;

            gap: 12px;

        }


        header h1 {

            color: #ffffff !important;

            font-size: 1.2rem;

            font-weight: 800;

            letter-spacing: 1.5px;

            text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.8);

        }


        @media (min-width: 576px) {

            header h1 { font-size: 1.4rem; }

        }


        .heineken-star {

            color: var(--heineken-red) !important;

            font-size: 1.8rem;

            animation: star-glow 2s infinite alternate;

        }


        @keyframes star-glow {

            from { text-shadow: 0 0 5px rgba(214, 26, 34, 0.5); transform: scale(1); }

            to { text-shadow: 0 0 15px rgba(214, 26, 34, 1), 0 0 25px rgba(214, 26, 34, 0.8); transform: scale(1.15); }

        }


        .user-panel {

            display: flex;

            align-items: center;

            gap: 10px;

            background: rgba(255, 255, 255, 0.2);

            padding: 6px 12px;

            border-radius: 20px;

        }


        .user-panel label {

            font-size: 0.85rem;

            font-weight: bold;

            color: #ffffff;

        }


        .user-panel select {

            background: var(--white);

            color: var(--dark-gray);

            border: none;

            padding: 4px 8px;

            border-radius: 4px;

            font-weight: bold;

            outline: none;

            cursor: pointer;

        }


        main {

            padding: 20px;

            max-width: 1200px;

            margin: 0 auto;

            z-index: 1;

        }


        .welcome-box {

            background-color: rgba(255, 255, 255, 0.95);

            color: var(--dark-gray);

            padding: 20px;

            border-radius: 12px;

            margin-bottom: 25px;

            box-shadow: 0 4px 15px rgba(0,0,0,0.2);

            display: flex;

            justify-content: space-between;

            align-items: center;

            flex-wrap: wrap;

            gap: 15px;

        }


        .welcome-box h2 {

            font-size: 1.2rem;

            color: var(--heineken-green);

        }


        .welcome-box p {

            font-size: 0.85rem;

            color: #444;

            margin-top: 4px;

        }


        .action-buttons {

            display: flex;

            gap: 10px;

            flex-wrap: wrap;

        }


        .dashboard-layout {

            display: grid;

            grid-template-columns: 1.6fr 1.4fr;

            gap: 20px;

        }


        @media (max-width: 992px) {

            .dashboard-layout {

                grid-template-columns: 1fr;

            }

        }


        .section-card {

            background: rgba(255, 255, 255, 0.95);

            color: var(--dark-gray);

            padding: 22px;

            border-radius: 12px;

            box-shadow: 0 8px 20px rgba(0,0,0,0.15);

            margin-bottom: 20px;

            border-top: 4px solid var(--heineken-green);

        }


        .section-card h2 {

            margin-bottom: 15px;

            font-size: 1.15rem;

            color: var(--heineken-green);

            border-bottom: 2px solid #ddd;

            padding-bottom: 8px;

            display: flex;

            align-items: center;

            gap: 8px;

        }


        .form-grid {

            display: grid;

            grid-template-columns: 1fr 1fr;

            gap: 12px;

        }


        @media (max-width: 768px) {

            .form-grid { grid-template-columns: 1fr; }

        }


        .input-group {

            text-align: left;

        }


        .input-group label {

            display: block;

            font-size: 0.8rem;

            margin-bottom: 4px;

            font-weight: bold;

            color: #444;

        }


        .input-group input, .input-group select {

            width: 100%;

            padding: 11px;

            border: 1px solid #ccc;

            border-radius: 6px;

            font-size: 0.95rem;

            outline: none;

            background: #fff;

        }


        .input-group input:focus, .input-group select:focus {

            border-color: var(--heineken-green);

            box-shadow: 0 0 5px rgba(0, 130, 74, 0.3);

        }


        .btn {

            padding: 12px;

            background-color: var(--heineken-green);

            color: var(--white);

            border: none;

            border-radius: 6px;

            font-size: 0.95rem;

            font-weight: bold;

            cursor: pointer;

            display: flex;

            justify-content: center;

            align-items: center;

            gap: 8px;

            transition: background 0.3s ease;

        }


        .btn:hover:not(:disabled) { opacity: 0.9; }

        .btn:disabled { background-color: #cccccc; cursor: not-allowed; }


        .btn-full { width: 100%; }

        .btn-warning { background-color: var(--warning-yellow); color: #212529; }

        .btn-secondary { background-color: #555; color: var(--white); }

        .btn-gold { background-color: #b8860b; color: white; }


        .quality-box {

            margin-top: 8px;

            padding: 10px;

            border-radius: 6px;

            display: none;

            font-size: 0.85rem;

            font-weight: bold;

        }

        .quality-good { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }

        .quality-bad { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }

        

        .brinde-box {

            background-color: #e2f0d9;

            color: #385723;

            border: 1px solid #c5e0b4;

            padding: 12px;

            border-radius: 6px;

            font-weight: bold;

            font-size: 0.95rem;

            margin-top: 5px;

            display: flex;

            align-items: center;

            gap: 10px;

        }


        .ranking-list { list-style: none; }

        .ranking-item {

            display: flex;

            justify-content: space-between;

            align-items: center;

            padding: 12px 10px;

            border-bottom: 1px solid #eee;

            font-size: 0.9rem;

        }

        .ranking-item.lider {

            background: linear-gradient(135deg, #fff9e6 0%, #fff2cc 100%);

            border-radius: 8px;

            font-weight: bold;

            border: 1.5px solid var(--gold);

        }


        .sales-board {

            display: grid;

            grid-template-columns: 1fr;

            gap: 10px;

            margin-top: 10px;

        }

        .sales-row {

            display: flex;

            justify-content: space-between;

            align-items: center;

            padding: 10px 15px;

            background: #f8f9fa;

            border-left: 4px solid #ccc;

            border-radius: 4px;

            font-size: 0.9rem;

        }

        .sales-row.winner {

            background: #e2f0d9;

            border-left-color: var(--heineken-green);

            font-weight: bold;

        }


        .table-responsive { overflow-x: auto; }

        table { width: 100%; border-collapse: collapse; margin-top: 10px; }

        th, td { text-align: left; padding: 12px; border-bottom: 1px solid #ddd; font-size: 0.85rem; }

        th { background-color: rgba(244, 246, 249, 0.8); color: #333; font-weight: bold; }

        .badge { padding: 3.5px 7px; border-radius: 12px; font-size: 0.75rem; font-weight: bold; }

        .badge-success { background-color: #d4edda; color: #155724; }

        .badge-danger { background-color: #f8d7da; color: #721c24; }

        .img-preview { width: 45px; height: 45px; object-fit: cover; border-radius: 6px; border: 1px solid #ccc; cursor: pointer; }


        /* MODAL DO CERTIFICADO HORIZONTAL (LANDSCAPE) */

        #certificateModal {

            display: none;

            position: fixed;

            top: 0; left: 0; width: 100%; height: 100%;

            background: rgba(0,0,0,0.85);

            z-index: 10000;

            justify-content: center;

            align-items: center;

            padding: 20px;

            overflow-y: auto;

        }

        .certificate-container {

            background: #fff;

            color: #333;

            width: 100%;

            max-width: 1050px; /* Largura estendida para proporção horizontal 4:3 / 16:9 */

            padding: 35px 50px;

            border: 15px double #00824a;

            border-radius: 4px;

            text-align: center;

            position: relative;

            box-shadow: 0 10px 30px rgba(0,0,0,0.5);

            display: flex;

            flex-direction: column;

            justify-content: space-between;

            min-height: 680px;

        }

        

        /* Layout interno com a imagem lateral */

        .cert-main-layout {

            display: flex;

            gap: 25px;

            align-items: center;

            text-align: center;

            flex: 1;

        }


        .cert-image-left {

            width: 110px;

            height: auto;

            object-fit: contain;

            flex-shrink: 0;

        }


        .cert-content-area {

            flex-grow: 1;

        }


        .cert-top-logo {

            max-width: 380px;

            height: auto;

            margin: 0 auto 15px auto;

            display: block;

            object-fit: contain;

        }


        .cert-header {

            font-family: 'Playfair Display', serif;

            font-size: 2.4rem;

            color: #00824a;

            margin-bottom: 5px;

            font-weight: 700;

        }

        .cert-sub {

            font-size: 1.1rem;

            text-transform: uppercase;

            letter-spacing: 3px;

            color: #d61a22;

            margin-bottom: 25px;

            font-weight: bold;

        }

        .cert-body {

            font-size: 1.2rem;

            line-height: 1.6;

            margin-bottom: 25px;

            color: #444;

        }

        .cert-body strong { 

            color: #00824a; 

            font-weight: 700;

        }

        

        /* ASSINATURAS EM TRÊS COLUNAS */

        .cert-footer-signatures {

            display: grid;

            grid-template-columns: 1fr 1fr 1fr;

            gap: 20px;

            margin-top: 30px;

            border-top: 1.5px solid #ddd;

            padding-top: 20px;

            font-size: 0.85rem;

        }

        .sig-block {

            display: flex;

            flex-direction: column;

            align-items: center;

            justify-content: flex-end;

        }

        .sig-line {

            width: 80%;

            border-top: 1px solid #888;

            margin-bottom: 8px;

        }

        .sig-title {

            font-weight: bold;

            color: #222;

        }

        .sig-sub {

            font-size: 0.75rem;

            color: #666;

        }


        /* CONFIGURAÇÃO ESPECÍFICA PARA IMPRESSÃO HORIZONTAL */

        @media print {

            @page {

                size: landscape;

                margin: 0;

            }

            body * {

                visibility: hidden;

            }

            #certificateModal, #certificateModal * {

                visibility: visible;

            }

            #certificateModal {

                position: absolute;

                left: 0;

                top: 0;

                width: 100vw;

                height: 100vh;

                background: #fff;

                padding: 0;

                display: flex;

                justify-content: center;

                align-items: center;

            }

            .certificate-container {

                border: 15px double #00824a;

                box-shadow: none;

                width: 100%;

                height: 100%;

                max-width: 100%;

                min-height: auto;

                padding: 40px;

                box-sizing: border-box;

            }

            .btn-print-action {

                display: none !important;

            }

        }

    </style>

</head>

<body>


    <!-- HEADER -->

    <header>

        <div class="header-title">

            <i class="fa-solid fa-star heineken-star"></i>

            <h1>HEINEKEN ON TRADE</h1>

        </div>

        <div class="user-panel">

            <label for="supervisorFilter"><i class="fa fa-user-tie"></i> Supervisor:</label>

            <select id="supervisorFilter" onchange="mudarSupervisor()"></select>

        </div>

    </header>


    <main>

        <div class="welcome-box">

            <div>

                <h2>Painel Ativo de Ativações</h2>

                <p>Registe e controle as vendas em campo e monitorize o desempenho de cada PDV.</p>

            </div>

            <div class="action-buttons">

                <button class="btn btn-secondary" onclick="exportarDados()"><i class="fa-solid fa-download"></i> Backup</button>

                <button id="syncBtn" class="btn btn-warning" onclick="sincronizarDados()"><i class="fa-solid fa-rotate"></i> Sinc (<span id="pendingCount">0</span>)</button>

            </div>

        </div>


        <div class="dashboard-layout">

            <!-- COLUNA ESQUERDA: FORMULÁRIO -->

            <div>

                <div class="section-card">

                    <h2><i class="fa fa-file-pen"></i> Registar Consumo do Cliente</h2>


                    <div class="form-grid">

                        <div class="input-group">

                            <label for="pdvSelector">Ponto de Venda (PDV)</label>

                            <select id="pdvSelector" onchange="atualizarRankingDoPdv()"></select>

                        </div>


                        <div class="input-group">

                            <label for="clienteNomeInput">Nome ou Mesa do Cliente</label>

                            <input type="text" id="clienteNomeInput" placeholder="Ex: Mesa 4" oninput="validarFormulario()">

                        </div>

                        

                        <div class="input-group">

                            <label for="vendasInput">Cervejas Compradas</label>

                            <input type="number" id="vendasInput" min="1" placeholder="Ex: 4" oninput="calcularBrindesSugeridos(); validarFormulario();">

                        </div>


                        <div class="input-group">

                            <label for="tempSelector">Temperatura</label>

                            <select id="tempSelector">

                                <option value="Gelada">Estupidamente Gelada</option>

                                <option value="Fria">Fria</option>

                                <option value="Quente">Quente</option>

                            </select>

                        </div>


                        <div class="input-group" style="grid-column: span 2;">

                            <label>Brinde Imediato Merecido</label>

                            <div id="brindeSugeridoBox" class="brinde-box">

                                <i class="fa-solid fa-gift"></i> <span id="textoBrinde">Insira a quantidade...</span>

                            </div>

                            <input type="hidden" id="brindeFinalValue" value="">

                        </div>

                        

                        <div class="input-group" style="grid-column: span 2;">

                            <label for="photoInput"><i class="fa-solid fa-camera"></i> Foto de Validação</label>

                            <input type="file" id="photoInput" accept="image/*" onchange="analisarQualidadeFoto(this)">

                            <div id="photoFeedback" class="quality-box"></div>

                        </div>

                    </div>

                    

                    <button id="btnSalvarRegisto" class="btn btn-full" style="margin-top: 15px;" onclick="guardarConsumoLocal()" disabled>

                        <i class="fa fa-plus"></i> Preencha os Dados Obrigatórios

                    </button>

                </div>

            </div>


            <!-- COLUNA DIREITA: MONITOR E RECONHECIMENTO -->

            <div>

                <div class="section-card">

                    <h2><i class="fa-solid fa-chart-line"></i> Controlo de Vendas por PDV</h2>

                    <div id="painelControloPDVs" class="sales-board"></div>

                    <button class="btn btn-full btn-gold" style="margin-top: 15px;" onclick="gerarCertificadoVencedor()">

                        <i class="fa-solid fa-award"></i> Emitir Certificado do Líder

                    </button>

                </div>


                <div class="section-card">

                    <h2><i class="fa-solid fa-trophy" style="color: var(--gold);"></i> Ranking de Mesas - PDV Ativo</h2>

                    <div id="rankingContainer">

                        <ul class="ranking-list" id="rankingListBody">

                            <li class="ranking-item" style="color: #888; text-align: center;">Sem vendas.</li>

                        </ul>

                    </div>

                </div>

            </div>

        </div>


        <!-- HISTÓRICO GLOBAL -->

        <div class="section-card">

            <h2><i class="fa-solid fa-list-check"></i> Histórico Completo de Registos</h2>

            <div class="table-responsive">

                <table>

                    <thead>

                        <tr>

                            <th>PDV</th>

                            <th>Foto</th>

                            <th>Promotores</th>

                            <th>Rep Sales</th>

                            <th>Cliente</th>

                            <th>Qtd Vendas</th>

                            <th>Brinde</th>

                            <th>Geleira</th>

                            <th>Sinc</th>

                        </tr>

                    </thead>

                    <tbody id="historicoTableBody"></tbody>

                </table>

            </div>

        </div>

    </main>


    <!-- POP-UP DE CERTIFICADO EM FORMATO HORIZONTAL (LANDSCAPE) -->

    <div id="certificateModal" onclick="fecharCertificado(event)">

        <div class="certificate-container" onclick="event.stopPropagation()">

            

            <!-- Logotipo do topo (Imagem 46205.jpg recortada conceitualmente ou inteira como cabeçalho) -->

            <img src="46205.jpg" alt="Heineken Premium Quality" class="cert-top-logo">

            

            <div class="cert-main-layout">

                <!-- Logotipo Vertical da lateral esquerda (Imagem 46206.jpg) -->

                <img src="46206.jpg" alt="Heineken" class="cert-image-left">

                

                <!-- Área principal de Texto -->

                <div class="cert-content-area">

                    <div class="cert-header">Certificado de Excelência</div>

                    <div class="cert-sub">Heineken On Trade Mozambique</div>

                    <div class="cert-body">

                        Este certificado é conferido com orgulho à equipa do ponto de venda:<br>

                        <strong id="certPdvName" style="font-size: 2rem; display: block; margin: 12px 0;">[Nome do PDV]</strong>

                        Pelo desempenho extraordinário, profissionalismo e liderança absoluta de vendas, registando um volume total de:

                        <strong id="certPdvTotal" style="font-size: 1.6rem; display: block; margin: 8px 0;">0 Cervejas Vendidas</strong>

                        <p style="font-size: 1.05rem; margin-top: 15px;">

                            Parabéns à equipa de Promotores: <strong id="certPromotores">--</strong>

                        </p>

                    </div>

                </div>

            </div>


            <!-- Rodapé de Assinaturas (Três campos para garantir a validação oficial) -->

            <div class="cert-footer-signatures">

                <div class="sig-block">

                    <div class="sig-line"></div>

                    <span class="sig-title" id="certSupervisor">--</span>

                    <span class="sig-sub">Supervisor de Operações</span>

                </div>

                <div class="sig-block">

                    <div class="sig-line"></div>

                    <span class="sig-title">Helio Herasmo Cabral</span>

                    <span class="sig-sub">Rep Sales Heineken</span>

                </div>

                <div class="sig-block">

                    <div class="sig-line"></div>

                    <span class="sig-title">Direção de Trade Marketing</span>

                    <span class="sig-sub">Heineken Moçambique</span>

                </div>

            </div>


            <button class="btn btn-full btn-secondary btn-print-action" style="margin-top: 25px;" onclick="window.print()">

                <i class="fa-solid fa-print"></i> Imprimir Certificado (Horizontal)

            </button>

        </div>

    </div>


    <script>

        const listaPDVs = [

            { "pdv": "Cervejaria Imperial", "promotores": "Texeira / Isabel Mussa", "supervisor": "Jessica Rafael", "rep": "Neutel" },

            { "pdv": "Sagres", "promotores": "Bejamim / Clotildes", "supervisor": "Jessica Rafael", "rep": "Neutel" },

            { "pdv": "Xima", "promotores": "Cintia karina / Gerson", "supervisor": "Mario", "rep": "Neutel" },

            { "pdv": "Volare", "promotores": "João Bonga / Nasma", "supervisor": "Agnaldo", "rep": "Neutel" },

            { "pdv": "Campo das Acacias", "promotores": "Cintia Malo / Idilson", "supervisor": "Monicia", "rep": "Neutel" },

            { "pdv": "Cantinho dos Artistas", "promotores": "Edilson / Carolina", "supervisor": "Tânia", "rep": "Neutel" },

            { "pdv": "Infinitos", "promotores": "Laque / Cândidoa", "supervisor": "Arnaldo", "rep": "Neutel" },

            { "pdv": "Guetto", "promotores": "Ermelinda / Eugénio", "supervisor": "Augusto", "rep": "Nelson" },

            { "pdv": "Nobre Paladar", "promotores": "Amarildo / Julina", "supervisor": "Telvino", "rep": "Jacinto" },

            { "pdv": "Witbank", "promotores": "Elsa / Alexandre", "supervisor": "Fred Junior", "rep": "Delivia" },

            { "pdv": "The Woods", "promotores": "Banu / Samuel", "supervisor": "Cleid", "rep": "Delivia" },

            { "pdv": "Babalaza", "promotores": "Glaucia / Leonildo", "supervisor": "Celma Mabunda", "rep": "Cintia" }

        ];


        let historicoConsumo = [];

        let fotoValida = false;

        let fotoBase64 = "";


        if (localStorage.getItem("heineken_consumo_planilha")) {

            try { historicoConsumo = JSON.parse(localStorage.getItem("heineken_consumo_planilha")); } catch (e) { historicoConsumo = []; }

        }


        window.onload = function() {

            carregarFiltroSupervisores();

            mudarSupervisor();

        };


        function validarFormulario() {

            const cliente = document.getElementById("clienteNomeInput").value.trim();

            const qtd = parseInt(document.getElementById("vendasInput").value) || 0;

            const btn = document.getElementById("btnSalvarRegisto");


            if (cliente !== "" && qtd > 0 && fotoValida) {

                btn.disabled = false;

                btn.innerHTML = "<i class='fa fa-plus'></i> Guardar Registo";

            } else {

                btn.disabled = true;

                btn.innerHTML = "<i class='fa fa-plus'></i> Preencha os Dados Obrigatórios";

            }

        }


        function atualizarPainelControloPDVs() {

            const container = document.getElementById("painelControloPDVs");

            container.innerHTML = "";


            const resumoPDVs = listaPDVs.map(p => {

                const totalVendas = historicoConsumo

                    .filter(item => item.pdv === p.pdv)

                    .reduce((acc, curr) => acc + curr.qtd, 0);

                return { ...p, total: totalVendas };

            }).sort((a, b) => b.total - a.total);


            const maxVendas = resumoPDVs[0].total;


            resumoPDVs.forEach(p => {

                const ehVencedor = p.total === maxVendas && maxVendas > 0;

                const rowClass = ehVencedor ? "sales-row winner" : "sales-row";

                container.innerHTML += `

                    <div class="${rowClass}">

                        <span>${ehVencedor ? '👑 ' : ''}<strong>${p.pdv}</strong> <small>(${p.supervisor})</small></span>

                        <span><strong>${p.total} un</strong></span>

                    </div>

                `;

            });

        }


        function gerarCertificadoVencedor() {

            const resumoPDVs = listaPDVs.map(p => {

                const total = historicoConsumo.filter(item => item.pdv === p.pdv).reduce((acc, curr) => acc + curr.qtd, 0);

                return { ...p, total };

            }).sort((a, b) => b.total - a.total);


            if (resumoPDVs.length === 0 || resumoPDVs[0].total === 0) {

                alert("Nenhuma venda registada para emitir reconhecimento!");

                return;

            }


            const vencedor = resumoPDVs[0];

            document.getElementById("certPdvName").innerText = vencedor.pdv;

            document.getElementById("certPdvTotal").innerText = `${vencedor.total} Unidades`;

            document.getElementById("certPromotores").innerText = vencedor.promotores;

            document.getElementById("certSupervisor").innerText = vencedor.supervisor;


            document.getElementById("certificateModal").style.display = "flex";

        }


        function fecharCertificado(e) {

            document.getElementById("certificateModal").style.display = "none";

        }


        function carregarFiltroSupervisores() {

            const filterSelect = document.getElementById("supervisorFilter");

            let supervisores = [...new Set(listaPDVs.map(p => p.supervisor))];

            

            let optTodos = document.createElement("option");

            optTodos.value = "todos";

            optTodos.text = "Todos (Visualizar Tudo)";

            filterSelect.add(optTodos);


            supervisores.forEach(sup => {

                if(sup !== "Sem Supervisor") {

                    let opt = document.createElement("option");

                    opt.value = sup;

                    opt.text = sup;

                    if(sup.toLowerCase() === "telvino") opt.selected = true;

                    filterSelect.add(opt);

                }

            });

        }


        function mudarSupervisor() {

            const supervisorSelecionado = document.getElementById("supervisorFilter").value;

            const selectPdv = document.getElementById("pdvSelector");

            selectPdv.innerHTML = "";


            const pdvsFiltrados = supervisorSelecionado === "todos" 

                ? listaPDVs 

                : listaPDVs.filter(p => p.supervisor === supervisorSelecionado);


            pdvsFiltrados.forEach(p => {

                let opt = document.createElement("option");

                opt.value = p.pdv;

                opt.text = p.pdv;

                selectPdv.add(opt);

            });


            atualizarPainelGeral();

        }


        function obterTextoBrindePorQtd(quantidade) {

            if (quantidade <= 0) return "";

            if (quantidade >= 10) {

                const blocks = Math.floor(quantidade / 10);

                return `${blocks * 2} Cervejas + ${blocks} Copo(s)`;

            } else if (quantidade >= 5) {

                return "1 Copo";

            } else {

                return "1 Cerveja";

            }

        }


        function calcularBrindesSugeridos() {

            const qtd = parseInt(document.getElementById("vendasInput").value) || 0;

            const texto = document.getElementById("textoBrinde");

            const brindeFinal = document.getElementById("brindeFinalValue");


            if (qtd <= 0) {

                text.innerText = "Insira a quantidade de cervejas...";

                brindeFinal.value = "";

            } else {

                const brindeGerado = obterTextoBrindePorQtd(qtd);

                texto.innerHTML = qtd >= 10 ? `🎉 Super Prémio: <strong>${brindeGerado}</strong>` : `🎁 Prémio Intermédio: <strong>${brindeGerado}</strong>`;

                brindeFinal.value = brindeGerado;

            }

        }


        function analisarQualidadeFoto(input) {

            const feedback = document.getElementById("photoFeedback");

            feedback.style.display = "block";

            if (!input.files || input.files.length === 0) { fotoValida = false; fotoBase64 = ""; validarFormulario(); return; }


            const file = input.files[0];

            if ((file.size / 1024) < 40) {

                feedback.className = "quality-box quality-bad";

                feedback.innerHTML = "❌ Imagem muito pequena ou sem foco!";

                fotoValida = false;

                fotoBase64 = "";

            } else {

                feedback.className = "quality-box quality-good";

                feedback.innerHTML = "✔️ Foto validada!";

                fotoValida = true;

                const reader = new FileReader();

                reader.onload = (e) => { fotoBase64 = e.target.result; };

                reader.readAsDataURL(file);

            }

            validarFormulario();

        }


        function guardarConsumoLocal() {

            const pdvNome = document.getElementById("pdvSelector").value;

            const cliente = document.getElementById("clienteNomeInput").value.trim();

            const qtd = parseInt(document.getElementById("vendasInput").value) || 0;

            const brinde = document.getElementById("brindeFinalValue").value;

            const temp = document.getElementById("tempSelector").value;


            if (!cliente || qtd <= 0 || !fotoValida) { alert("Preencha todos os campos corretamente com foto válida."); return; }


            const pdvInfo = listaPDVs.find(p => p.pdv === pdvNome);

            const clienteExistente = historicoConsumo.find(item => item.pdv === pdvNome && item.cliente.toLowerCase() === cliente.toLowerCase());


            if (clienteExistente) {

                clienteExistente.qtd += qtd;

                clienteExistente.brinde = obterTextoBrindePorQtd(clienteExistente.qtd);

                if (fotoBase64) clienteExistente.foto = fotoBase64;

                clienteExistente.sincronizado = false;

            } else {

                historicoConsumo.push({

                    pdv: pdvNome, promotores: pdvInfo.promotores, rep: pdvInfo.rep,

                    cliente, qtd, brinde: brinde || "Nenhum", temp,

                    sincronizado: false, supervisor: pdvInfo.supervisor, foto: fotoBase64

                });

            }


            try {

                localStorage.setItem("heineken_consumo_planilha", JSON.stringify(historicoConsumo));

                alert(`✔️ Salvo! ${cliente} com acumulado de ${clienteExistente ? clienteExistente.qtd : qtd} un.`);

            } catch (e) {

                alert("Armazenamento cheio! Remova fotos pesadas.");

                return;

            }


            document.getElementById("clienteNomeInput").value = "";

            document.getElementById("vendasInput").value = "";

            document.getElementById("photoInput").value = "";

            document.getElementById("photoFeedback").style.display = "none";

            document.getElementById("textoBrinde").innerText = "Insira a quantidade...";

            fotoBase64 = "";

            fotoValida = false;


            validarFormulario();

            atualizarPainelGeral();

        }


        function atualizarRankingDoPdv() {

            const pdvAtual = document.getElementById("pdvSelector").value;

            const rankingList = document.getElementById("rankingListBody");

            rankingList.innerHTML = "";


            const consumosDoPdv = historicoConsumo.filter(item => item.pdv === pdvAtual).sort((a, b) => b.qtd - a.qtd);

            if (consumosDoPdv.length === 0) {

                rankingList.innerHTML = `<li class="ranking-item" style="color: #888; text-align: center;">Nenhuma venda neste PDV.</li>`;

                return;

            }


            const maxCervejas = consumosDoPdv[0].qtd;

            consumosDoPdv.forEach((item, index) => {

                let ehLider = item.qtd === maxCervejas;

                rankingList.innerHTML += `

                    <li class="${ehLider ? 'ranking-item lider' : 'ranking-item'}">

                        <div>

                            <span>${index+1}º ${ehLider ? '👑 ' : ''}${item.cliente}</span>

                        </div>

                        <span><strong>${item.qtd} un</strong></span>

                    </li>

                `;

            });

        }


        function atualizarPainelGeral() {

            atualizarRankingDoPdv();

            atualizarPainelControloPDVs();


            const pendentes = historicoConsumo.filter(item => !item.sincronizado).length;

            document.getElementById("pendingCount").innerText = pendentes;


            const tbody = document.getElementById("historicoTableBody");

            tbody.innerHTML = "";


            const supervisorSelecionado = document.getElementById("supervisorFilter").value;

            const dadosVisiveis = supervisorSelecionado === "todos" 

                ? historicoConsumo 

                : historicoConsumo.filter(item => item.supervisor === supervisorSelecionado);


            if(dadosVisiveis.length === 0) {

                tbody.innerHTML = `<tr><td colspan="9" style="text-align:center; color:#888;">Sem registos.</td></tr>`;

                return;

            }


            dadosVisiveis.forEach(item => {

                let row = `

                    <tr>

                        <td><strong>${item.pdv}</strong></td>

                        <td>${item.foto ? `<img src="${item.foto}" class="img-preview" onclick="abrirModalFoto('${item.foto}')">` : '<span style="color:#aaa;">Sem foto</span>'}</td>

                        <td>${item.promotores}</td>

                        <td>${item.rep}</td>

                        <td>${item.cliente}</td>

                        <td><strong>${item.qtd} un</strong></td>

                        <td>${item.brinde}</td>

                        <td><span class="badge badge-success">${item.temp}</span></td>

                        <td><span class="badge ${item.sincronizado ? 'badge-success':'badge-danger'}">${item.sincronizado ? 'Sim':'Não'}</span></td>

                    </tr>

                `;

                tbody.innerHTML += row;

            });

        }


        function abrirModalFoto(srcBase64) {

            const popup = window.open();

            if (popup) popup.document.write(`<iframe src="${srcBase64}" frameborder="0" style="width:100%; height:100%;"></iframe>`);

        }


        function exportarDados() {

            if (historicoConsumo.length === 0) { alert("Sem dados."); return; }

            const downloadAnchor = document.createElement('a');

            downloadAnchor.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(historicoConsumo, null, 2)));

            downloadAnchor.setAttribute("download", `heineken_backup.json`);

            document.body.appendChild(downloadAnchor);

            downloadAnchor.click();

            downloadAnchor.remove();

        }


        function sincronizarDados() {

            const pendentes = historicoConsumo.filter(item => !item.sincronizado);

            if (pendentes.length === 0) { alert("Tudo sincronizado!"); return; }


            const btn = document.getElementById("syncBtn");

            btn.innerHTML = `<i class="fa-solid fa-spinner fa-spin"></i> A enviar...`;

            btn.disabled = true;


            setTimeout(() => {

                historicoConsumo.forEach(item => item.sincronizado = true);

                localStorage.setItem("heineken_consumo_planilha", JSON.stringify(historicoConsumo));

                alert("🎉 Turno sincronizado com a central!");

                btn.disabled = false;

                btn.innerHTML = `<i class="fa-solid fa-rotate"></i> Sincronizar (0)`;

                atualizarPainelGeral();

            }, 1500);

        }

    </script>

</body>

</html>

Postagens mais visitadas deste blog

Veja o video completo aqui

Assistir o vídeo completo aqui