html Briefing de Gestão de Mídias Sociais - VIX /* Variáveis de Cores */ :root { --primary-color: #007BFF; /* Azul */
--secondary-color: #d7c3a8; /* Bege/Terroso */
--accent-color: #3b412c; /* Verde Escuro */
--bg-light: #f8f9fa; /* Fundo claro */
--card-bg-gradient: linear-gradient(145deg, #ffffff, #f0f0f0); /* Degradê suave para cards */
--shadow-light: rgba(0, 0, 0, 0.05); /* Sombra suave */
--text-muted: #6c757d; /* Texto dica */ } body { font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background-color: var(--bg-light);
display: flex;
justify-content: center;
align-items: flex-start; /* Alinha ao topo */
min-height: 100vh;
padding: 20px 0; } .form-container { max-width: 900px;
width: 100%;
background-color: #fff;
border-radius: 15px;
box-shadow: 0 10px 30px var(--shadow-light);
padding: 30px;
margin-top: 20px; /* Espaço do topo */ } .logo-header { max-height: 60px;
margin-bottom: 25px;
display: block;
margin-left: auto;
margin-right: auto; } h2.form-title { color: var(--accent-color);
font-weight: 700;
text-align: center;
margin-bottom: 30px; } /* Estilos do Stepper */ .stepper-wrapper { display: flex;
justify-content: space-between;
margin-bottom: 40px;
position: relative;
padding: 0 10px; } .stepper-wrapper::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 2px;
background-color: #e0e0e0;
transform: translateY(-50%);
z-index: 0; } .stepper-item { display: flex;
flex-direction: column;
align-items: center;
flex: 1;
position: relative;
z-index: 1;
cursor: pointer;
transition: all 0.3s ease; } .stepper-item.completed .step-counter { background-color: var(--primary-color); /* Cor de fundo para passos completos */
color: #fff; } .stepper-item.completed .step-counter i { color: #fff; } .stepper-item.active .step-counter { border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); } .stepper-item.active .step-name { color: var(--primary-color);
font-weight: 600; } .step-counter { width: 40px;
height: 40px;
border-radius: 50%;
background-color: #fff;
border: 2px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 8px;
font-size: 18px;
color: #ccc;
transition: all 0.3s ease; } .step-counter i { color: #ccc;
transition: all 0.3s ease; } .step-name { font-size: 13px;
text-align: center;
color: #888;
transition: all 0.3s ease; } /* Cores específicas dos ícones do stepper */ .stepper-item[data-step="1"] .step-counter i { color: #007BFF; }
.stepper-item[data-step="2"] .step-counter i { color: #17A2B8; }
.stepper-item[data-step="3"] .step-counter i { color: #28A745; }
.stepper-item[data-step="4"] .step-counter i { color: #FFC107; }
.stepper-item[data-step="5"] .step-counter i { color: #E83E8C; }
.stepper-item[data-step="6"] .step-counter i { color: #6F42C1; } /* Cores de fundo dos ícones do stepper quando completos */ .stepper-item.completed[data-step="1"] .step-counter { background-color: #007BFF; }
.stepper-item.completed[data-step="2"] .step-counter { background-color: #17A2B8; }
.stepper-item.completed[data-step="3"] .step-counter { background-color: #28A745; }
.stepper-item.completed[data-step="4"] .step-counter { background-color: #FFC107; }
.stepper-item.completed[data-step="5"] .step-counter { background-color: #E83E8C; }
.stepper-item.completed[data-step="6"] .step-counter { background-color: #6F42C1; } /* Cores dos ícones do stepper quando completos (branco) */ .stepper-item.completed .step-counter i { color: #fff !important; } /* Barra de Progresso */ .progress { height: 8px;
margin-bottom: 30px;
border-radius: 5px;
background-color: #e9ecef; } .progress-bar { background-color: var(--primary-color);
border-radius: 5px;
transition: width 0.5s ease-in-out; } /* Passos do Formulário */ .form-step { display: none;
animation: fadeIn 0.5s ease-out; } .form-step.active { display: block; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); } } .card-custom { background: var(--card-bg-gradient);
border: none;
border-radius: 10px;
box-shadow: 0 5px 15px var(--shadow-light);
padding: 25px;
margin-bottom: 25px; } .form-label { font-weight: 600;
color: var(--accent-color);
margin-bottom: 8px; } .form-control, .form-select { border-radius: 8px;
border: 1px solid #ced4da;
padding: 10px 15px;
transition: all 0.3s ease; } .form-control:focus, .form-select:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 0.25rem rgba(0, 123, 255, 0.25); } .form-control::placeholder {
color: #adb5bd;
font-style: italic; } .form-text { font-size: 0.85em;
color: var(--text-muted);
margin-top: 5px; } /* Botões */ .btn-primary { background-color: var(--primary-color);
border-color: var(--primary-color);
border-radius: 8px;
padding: 10px 25px;
font-weight: 600;
transition: all 0.3s ease; } .btn-primary:hover {
background-color: #0056b3;
border-color: #0056b3;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 123, 255, 0.2); } .btn-secondary { background-color: var(--secondary-color);
border-color: var(--secondary-color);
color: var(--accent-color);
border-radius: 8px;
padding: 10px 25px;
font-weight: 600;
transition: all 0.3s ease; } .btn-secondary:hover {
background-color: #c0b09a;
border-color: #c0b09a;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(215, 195, 168, 0.3); } .form-check-input:checked {
background-color: var(--primary-color);
border-color: var(--primary-color); } .form-check-label i { margin-right: 8px;
color: var(--primary-color); /* Cor padrão para ícones de checkboxes */ } /* Ajustes Responsivos */ @media (max-width: 768px) { .stepper-wrapper { flex-wrap: wrap;
justify-content: center; } .stepper-item { flex: none;
width: 33%; /* 3 itens por linha */
margin-bottom: 20px; } .stepper-wrapper::before {
display: none; /* Esconde a linha em telas pequenas */ } .form-container { padding: 20px;
margin-top: 10px; } .logo-header { max-height: 50px; } } @media (max-width: 576px) { .stepper-item { width: 50%; /* 2 itens por linha */ } .stepper-item .step-name { font-size: 11px; } .step-counter { width: 35px;
height: 35px;
font-size: 16px; } } Briefing de Gestão de Mídias Sociais Identificação Cliente Empresa Concorrência Público-Alvo Projeto Identificação Responsável pelo Briefing Por favor, preencha o nome do responsável. Data Preenchida automaticamente com a data de hoje Próximo Cliente Nome da Empresa Por favor, preencha o nome da empresa. Produto/Serviço Principal Por favor, preencha o produto/serviço principal. Responsável pela Empresa Por favor, preencha o responsável pela empresa. Email Por favor, preencha um email válido. Telefone Por favor, preencha um telefone válido. Anterior Próximo Empresa Breve Histórico Por favor, preencha o histórico da empresa. Produtos/Serviços Por favor, descreva os produtos/serviços. Site Por favor, preencha um URL de site válido. Redes Sociais Atuais Por favor, liste as redes sociais atuais. Preços no Mercado Por favor, descreva os preços no mercado. Distribuição Por favor, descreva a distribuição da empresa. Anterior Próximo Concorrência Principais Concorrentes Por favor, liste os principais concorrentes. Preço/Distribuição dos Concorrentes Por favor, descreva a estratégia de preço/distribuição dos concorrentes. Pontos Fortes e Fracos dos Concorrentes Por favor, descreva os pontos fortes e fracos dos concorrentes. Anterior Próximo Público-Alvo Persona Por favor, descreva a persona. Hábitos e Comportamentos Por favor, descreva os hábitos e comportamentos do público-alvo. Razões de Aquisição Por favor, descreva as razões de aquisição. Anterior Próximo Projeto Redes Sociais a Gerenciar Facebook Instagram TikTok LinkedIn Twitter/X YouTube Outras Por favor, especifique as outras redes sociais. Objetivos Principais Pode marcar mais de um objetivo Vender produtos físicos Vender cursos/serviços Captar leads/orçamentos Apresentar produtos/serviços Distribuir conteúdo/educar Mensagem Principal Por favor, preencha a mensagem principal. Tom de Voz Como a empresa fala com seus clientes? Corporativo Didático Moderno Formal Informal Humor Jovem/Descontraído Por favor, selecione o tom de voz. Problemas Atuais Por favor, descreva os problemas atuais. Vantagens Atuais Por favor, descreva as vantagens atuais. Postagens por Semana Por favor, preencha o número de postagens por semana. Verba para Anúncios (R$) Por favor, preencha a verba para anúncios. Lista de Referências Por favor, liste pelo menos 3 perfis de referência. Lista de Exclusão Por favor, liste pelo menos 3 perfis de exclusão. Adicionar Compra de Fotos/Vídeos Por favor, descreva se deseja comprar fotos/vídeos. Adicionar Produção de Fotos/Vídeos Por favor, descreva se deseja produção de fotos/vídeos. Prazo para Finalizar Por favor, preencha o prazo para finalizar. Anterior Enviar Briefing Fechar Novo Briefing const form = document.getElementById('briefingForm'); const formSteps = document.querySelectorAll('.form-step'); const stepperItems = document.querySelectorAll('.stepper-item'); const progressBar = document.querySelector('.progress-bar'); const prevButtons = document.querySelectorAll('.prev-step'); const nextButtons = document.querySelectorAll('.next-step'); const submitButton = document.getElementById('submitBtn'); const feedbackModal = new bootstrap.Modal(document.getElementById('feedbackModal')); const feedbackModalLabel = document.getElementById('feedbackModalLabel'); const feedbackModalBody = document.getElementById('feedbackModalBody'); const resetFormBtn = document.getElementById('resetFormBtn'); const outrasRedesCheckbox = document.getElementById('redeOutras'); const outrasRedesContainer = document.getElementById('outrasRedesContainer'); const outrasRedesInput = document.getElementById('outrasRedes'); let currentStep = 0; const totalSteps = formSteps.length; // URL do Google Apps Script (SUBSTITUA PELA SUA ID DE IMPLANTAÇÃO REAL) const SCRIPT_URL = 'https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec'; // --- Funções Auxiliares --- function showStep(stepIndex) { formSteps.forEach((step, index) => { step.classList.toggle('active', index === stepIndex); }); currentStep = stepIndex; updateStepperUI(); } function updateStepperUI() { stepperItems.forEach((item, index) => { item.classList.toggle('active', index === currentStep); item.classList.toggle('completed', index < currentStep); }); const progress = ((currentStep + 1) / totalSteps) * 100; progressBar.style.width = `${progress}%`; progressBar.setAttribute('aria-valuenow', progress); } function validateStep(stepIndex) { const currentFormStep = formSteps[stepIndex]; let isValid = true; const requiredInputs = currentFormStep.querySelectorAll('[required]'); requiredInputs.forEach(input => { if (input.type === 'checkbox') { // Para grupos de checkboxes, verifica se pelo menos um está marcado const checkboxGroup = document.querySelectorAll(`input[name="${input.name}"]:checked`); if (checkboxGroup.length === 0) { isValid = false; input.classList.add('is-invalid'); } else { input.classList.remove('is-invalid'); } } else if (input.type === 'radio') { // Para grupos de radio buttons, verifica se pelo menos um está marcado const radioGroup = document.querySelectorAll(`input[name="${input.name}"]:checked`); if (radioGroup.length === 0) { isValid = false; input.classList.add('is-invalid'); } else { input.classList.remove('is-invalid'); } } else if (input.value.trim() === '') { isValid = false; input.classList.add('is-invalid'); } else { input.classList.remove('is-invalid'); } }); // Validação específica para "Outras Redes" se marcada if (stepIndex === 5 && outrasRedesCheckbox.checked && outrasRedesInput.value.trim() === '') { isValid = false; outrasRedesInput.classList.add('is-invalid'); } else if (stepIndex === 5 && outrasRedesCheckbox.checked) { outrasRedesInput.classList.remove('is-invalid'); } return isValid; } function autoFillDate() { const today = new Date(); const yyyy = today.getFullYear(); const mm = String(today.getMonth() + 1).padStart(2, '0'); // Meses começam em 0! const dd = String(today.getDate()).padStart(2, '0'); document.getElementById('dataBriefing').value = `${yyyy}-${mm}-${dd}`; } function toggleOutrasRedesInput() { if (outrasRedesCheckbox.checked) { outrasRedesContainer.style.display = 'block'; outrasRedesInput.setAttribute('required', 'true'); } else { outrasRedesContainer.style.display = 'none'; outrasRedesInput.removeAttribute('required'); outrasRedesInput.classList.remove('is-invalid'); // Limpa validação se escondido outrasRedesInput.value = ''; // Limpa valor se escondido } } // --- Listeners de Eventos --- nextButtons.forEach(button => { button.addEventListener('click', () => { if (validateStep(currentStep)) { if (currentStep < totalSteps - 1) { showStep(currentStep + 1); } } }); }); prevButtons.forEach(button => { button.addEventListener('click', () => { if (currentStep > 0) { showStep(currentStep - 1); } }); }); stepperItems.forEach((item, index) => { item.addEventListener('click', () => { // Permite navegação direta apenas para passos anteriores ou o passo atual, // ou para o próximo passo se o atual for validado. if (index < currentStep || (index === currentStep) || (index === currentStep + 1 && validateStep(currentStep))) { showStep(index); } }); }); outrasRedesCheckbox.addEventListener('change', toggleOutrasRedesInput); form.addEventListener('submit', async (e) => { e.preventDefault(); if (!validateStep(currentStep)) { return; } submitButton.disabled = true; submitButton.querySelector('.spinner-border').classList.remove('d-none'); submitButton.querySelector('i').classList.add('d-none'); const formData = new FormData(form); const data = {}; for (let [key, value] of formData.entries()) { // Lida com múltiplos checkboxes com o mesmo nome if (key === 'Redes Sociais a Gerenciar' || key === 'Objetivos Principais') { if (!data[key]) { data[key] = []; } data[key].push(value); } else { data[key] = value; } } // Adiciona timestamp data['Data de Resposta'] = new Date().toLocaleString('pt-BR', { timeZone: 'America/Sao_Paulo' }); try { const response = await fetch(SCRIPT_URL, { method: 'POST',
mode: 'no-cors', // Necessário para Google Apps Script
headers: {
'Content-Type': 'application/json', }, body: JSON.stringify(data), }); // Como o modo 'no-cors' é usado, não podemos ler diretamente response.ok ou response.json() // Assumimos sucesso se nenhum erro de rede ocorreu. feedbackModalLabel.textContent = 'Sucesso!'; feedbackModalLabel.style.color = 'var(--primary-color)'; feedbackModalBody.innerHTML = '

Seu briefing foi enviado com sucesso! Agradecemos sua colaboração.

'; resetFormBtn.style.display = 'inline-block'; feedbackModal.show(); } catch (error) { console.error('Erro ao enviar o formulário:', error); feedbackModalLabel.textContent = 'Erro!'; feedbackModalLabel.style.color = '#dc3545'; feedbackModalBody.innerHTML = `

Ocorreu um erro ao enviar seu briefing. Por favor, tente novamente mais tarde. Detalhes: ${error.message}

`; resetFormBtn.style.display = 'none'; feedbackModal.show(); } finally { submitButton.disabled = false; submitButton.querySelector('.spinner-border').classList.add('d-none'); submitButton.querySelector('i').classList.remove('d-none'); } }); resetFormBtn.addEventListener('click', () => { form.reset(); form.querySelectorAll('.is-invalid').forEach(el => el.classList.remove('is-invalid')); showStep(0); feedbackModal.hide(); toggleOutrasRedesInput(); // Reseta a visibilidade do input 'Outras Redes' autoFillDate(); // Preenche a data novamente }); // --- Configuração Inicial --- document.addEventListener('DOMContentLoaded', () => { autoFillDate(); showStep(0); // Mostra o primeiro passo toggleOutrasRedesInput(); // Inicializa a visibilidade do input 'Outras Redes' }); --- ### Código para Google Apps Script Este código deve ser colado no editor do Google Apps Script associado à sua planilha. ```javascript /** * Google Apps Script para receber dados de formulário via POST e gravar em uma planilha. * * INSTRUÇÕES: * 1. Crie uma nova planilha no Google Sheets (ex: "Briefings de Mídias Sociais VIX"). * 2. Abra o Google Apps Script: Na sua planilha, vá em "Extensões" > "Apps Script". * 3. Copie e cole este código no editor do Apps Script, substituindo qualquer código existente. * 4. Salve o projeto (ícone de disquete ou Ctrl+S/Cmd+S). Você pode dar um nome ao projeto. * 5. Implante o script como um aplicativo da web: * - Clique em "Implantar" (Deploy) > "Nova implantação" (New deployment). * - Selecione o tipo "Aplicativo da Web" (Web app). * - Configure: * - "Executar como": Seu e-mail (Eu) * - "Quem tem acesso": Qualquer pessoa (Anyone) * - Clique em "Implantar". * - Se solicitado, autorize o script (pode exigir que você clique em "Avançado" e depois "Ir para [Nome do Projeto] (não seguro)"). * 6. Copie o "URL do aplicativo da Web" (Web app URL) que será exibido após a implantação. * 7. Cole este URL no código HTML do formulário, substituindo 'https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec'. * 8. Teste o formulário no navegador. */ function doPost(e) { var sheetName = "Respostas Briefing"; // Nome da aba na sua planilha onde os dados serão salvos var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName(sheetName); // Se a aba não existir, crie-a if (!sheet) { sheet = ss.insertSheet(sheetName); } var data = JSON.parse(e.postData.contents); var headers = []; var rowData = []; // Obter cabeçalhos da primeira linha da planilha ou criar novos if (sheet.getLastRow() === 0) { // Se a planilha estiver vazia, crie os cabeçalhos com base nas chaves do JSON headers = Object.keys(data); sheet.appendRow(headers); } else { // Se já houver cabeçalhos, use-os headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; // Adiciona novos cabeçalhos se existirem no JSON e não na planilha Object.keys(data).forEach(function(key) { if (headers.indexOf(key) === -1) { headers.push(key); sheet.getRange(1, sheet.getLastColumn() + 1).setValue(key); // Adiciona o novo cabeçalho } }); } // Preencher os dados da linha na ordem dos cabeçalhos for (var i = 0; i < headers.length; i++) { var header = headers[i]; var value = data[header]; // Tratar arrays (checkboxes) para que sejam salvos como uma string separada por vírgulas if (Array.isArray(value)) { rowData.push(value.join(', ')); } else { rowData.push(value); } } sheet.appendRow(rowData); // Retornar uma resposta de sucesso (necessário para o fetch, mesmo em no-cors) return ContentService.createTextOutput(JSON.stringify({ 'result': 'success', 'message': 'Dados recebidos com sucesso!' })) .setMimeType(ContentService.MimeType.JSON); } ```