Created
April 14, 2025 15:12
-
-
Save Santosl2/2c0cd8214e68394b07bff85289bfbb43 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="pt-br"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Formulário de Leads</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com" /> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" | |
| rel="stylesheet" | |
| /> | |
| <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/vue-select@4.0.0-beta.6/dist/vue-select.umd.js"></script> | |
| <link | |
| rel="stylesheet" | |
| href="https://unpkg.com/vue-select@latest/dist/vue-select.css" | |
| /> | |
| <style> | |
| html, | |
| body { | |
| font-family: "Montserrat", sans-serif !important; | |
| } | |
| :root { | |
| --vs-border-radius: 17px; | |
| } | |
| .rounded-custom, | |
| .v-select { | |
| border-radius: 17px; | |
| } | |
| .title-color { | |
| color: #feb702 !important; | |
| } | |
| .loader { | |
| border-top-color: transparent; | |
| border-radius: 50%; | |
| animation: spin 0.6s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { | |
| transform: rotate(0deg); | |
| } | |
| 100% { | |
| transform: rotate(360deg); | |
| } | |
| } | |
| button { | |
| all: unset; | |
| border: none !important; | |
| } | |
| </style> | |
| </head> | |
| <body | |
| class="bg-[#012030] flex justify-center items-center min-h-screen flex-1 w-full flex-col" | |
| id="app" | |
| > | |
| <section id="section" class="w-full text-center space-y-10 px-5 py-4"> | |
| <div class="hidden"> | |
| <h1 class="text-4xl font-extrabold text-[#feb702]"> | |
| Formulário de Leads | |
| </h1> | |
| <p class="text-white"> | |
| Preencha os dados para buscar leads disponíveis | |
| </p> | |
| </div> | |
| <div v-if="loadingInicial" class="text-center text-gray-500"> | |
| Carregando... | |
| </div> | |
| <form | |
| v-if="!loadingInicial && !mostrarResultados" | |
| @submit.prevent="buscarLeads" | |
| class="px-6 border rounded-custom py-10 space-y-4 bg-white shadow" | |
| > | |
| <div | |
| class="flex flex-col md:flex-row gap-10 md:items-start w-full mb-10" | |
| > | |
| <div class="form-group flex-1 text-left"> | |
| <label | |
| for="estado" | |
| class="block text-left font-semibold mb-2 text-gray-700 text-2xl" | |
| >Estado</label | |
| > | |
| <v-select | |
| v-model="estadoSelecionado" | |
| required | |
| :disabled="todoBrasil" | |
| :options="Object.keys(estados)" | |
| :close-on-select="false" | |
| multiple | |
| :placeholder="todoBrasil ? 'Todo o Brasil' : 'Selecione o(s) estado(s):'" | |
| > | |
| </v-select> | |
| <small | |
| class="text-red-500 font-bold" | |
| v-if="estadoSelecionado.length >= 4" | |
| >* No máximo 3 estados ou Todo o Brasil</small | |
| > | |
| <label class="flex mt-2 items-center space-x-2"> | |
| <input | |
| type="checkbox" | |
| v-model="todoBrasil" | |
| @change="limparEstadosCidade" | |
| class="form-checkbox size-3 text-blue-600 rounded-custom focus:ring-0 border-gray-300" | |
| /> | |
| <span class="text-gray-700 text-sm">Selecionar Brasil todo</span> | |
| </label> | |
| </div> | |
| <div class="form-group flex-1 text-left"> | |
| <label | |
| for="cidade" | |
| class="block text-left text-2xl font-semibold text-gray-700 mb-2" | |
| >Cidade</label | |
| > | |
| <v-select | |
| v-model="cidadeSelecionada" | |
| required | |
| :disabled="todoBrasil || todosAsCidades" | |
| :close-on-select="false" | |
| multiple | |
| taggable | |
| :placeholder="todosAsCidades ? 'Todos as cidades do(s) Estados' : todoBrasil ? 'Todo o Brasil' : 'Escreva a(s) cidade(s):'" | |
| > | |
| <template #no-options="{ search, searching, loading }"> | |
| Escreva o nome da cidade e aperte enter para adicionar | |
| </template> | |
| </v-select> | |
| <small | |
| >Escreva o nome da cidade e aperte enter para adicionar</small | |
| > | |
| <label class="flex mt-2 items-center space-x-2"> | |
| <input | |
| type="checkbox" | |
| v-model="todosAsCidades" | |
| @change="limparCidades" | |
| :disabled="todoBrasil" | |
| class="form-checkbox size-3 text-blue-600 rounded focus:ring-0 border-gray-300" | |
| /> | |
| <span class="text-gray-700 text-sm" | |
| >Selecionar Todas as cidades do Estado(s)</span | |
| > | |
| </label> | |
| </div> | |
| </div> | |
| <div class="form-group"> | |
| <div class="form-group flex-1 text-left"> | |
| <label | |
| for="nichosNovos" | |
| class="block text-left font-semibold mb-2 text-gray-700 text-2xl" | |
| >Nichos</label | |
| > | |
| <v-select | |
| required | |
| :options='[ | |
| "Consorcio (Carro, Moto, Imóvel)", | |
| "Plano de Saúde (PJ, PF)", | |
| "FGTS", | |
| "Seguros/Proteção Veicular", | |
| "Direito/Advocacia", | |
| "Empréstimo Consignado", | |
| "Imóveis (Baixo, Médio e Alto Padrão)", | |
| "Produtos e serviços femininos", | |
| "Energia solar", | |
| "B2B/ Empresas", | |
| "Educação/Graduação", | |
| "Clinicas/Consultorios", | |
| "Outros", | |
| ]' | |
| v-model="nichosNovosSelecionados" | |
| :close-on-select="false" | |
| multiple | |
| :placeholder="'Selecione o(s) nicho(s):'" | |
| > | |
| </v-select> | |
| <input | |
| v-if="mostrarOutros" | |
| type="text" | |
| v-model="nichoCustomizado" | |
| placeholder="Digite o nicho" | |
| class="mt-2 p-2 border border-gray-300 rounded-custom w-full" | |
| /> | |
| </div> | |
| </div> | |
| <div class="h-5"></div> | |
| <button | |
| type="submit" | |
| :disabled="mostrarOutros && !nichoCustomizado || carregandoLeads || estadoSelecionado.length >= 4 || !todoBrasil && (!estadoSelecionado || !todosAsCidades && !cidadeSelecionada)" | |
| class="w-full bg-[#feb702] max-w-[180px] text-gray-800 font-semibold py-2 px-4 rounded-custom mt-10 justify-center flex items-center border-transparent disabled:opacity-70 m-auto disabled:cursor-not-allowed justify-center space-x-2 border-transparent" | |
| > | |
| <span | |
| v-if="carregandoLeads" | |
| class="loader mr-2 w-4 h-4 border-2 border-t-transparent border-white rounded-custom animate-spin" | |
| ></span> | |
| <span>{{ carregandoLeads ? 'Buscando...' : 'Buscar Leads' }}</span> | |
| </button> | |
| </form> | |
| <div v-if="mostrarResultados" class="mt-6"> | |
| <h2 class="text-2xl font-extrabold text-left text-[#feb702]"> | |
| Leads Disponíveis: | |
| <span class="text-white font-medium" | |
| >{{leadsDisponiveis.toLocaleString('pt-BR')}}</span | |
| > | |
| </h2> | |
| <div class="text-white text-left mt-6"> | |
| <strong class="font-bold block text-left"> | |
| Estado(s) selecionados: | |
| <span class="font-normal"> | |
| <template v-if="!todoBrasil"> | |
| {{estadoSelecionado.map(e => estados[e]).join(', ')}}</template | |
| > | |
| <template v-else> Todo o Brasil </template> | |
| </span> | |
| </strong> | |
| <strong class="font-bold block" | |
| >Cidade(s) selecionadas: | |
| <span class="font-normal"> | |
| <template v-if="!todoBrasil && !todosAsCidades" | |
| >{{cidadeSelecionada.join(', ')}}</template | |
| > | |
| <template v-if="todoBrasil"> Todo o Brasil </template> | |
| <template v-if="todosAsCidades"> | |
| Todo as Cidades do Estado | |
| </template> | |
| </span></strong | |
| > | |
| </div> | |
| <div class="mt-4 space-y-3"> | |
| <div | |
| v-for="(produto, index) in produtos" | |
| :key="produto.name" | |
| :class="['p-4 border rounded-custom bg-gray-100 flex justify-between items-center', produto.maisVendido && 'border-green-500']" | |
| > | |
| <div class="text-left"> | |
| <div | |
| v-if="produto.maisVendido" | |
| class="block items-center rounded-custom border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 border-transparent bg-green-500 w-max text-white shadow hover:bg-green-500/80" | |
| > | |
| Mais vendido | |
| </div> | |
| <small class="text-gray-600"> {{ produto.name }} </small> | |
| <h2 class="text-xl font-semibold text-left"> | |
| {{ String(produto?.quantity)?.replace('{disponiveis}', | |
| leadsDisponiveis.toLocaleString('pt-BR')) }} leads | |
| </h2> | |
| <p class="text-lg">{{ moneyFormat(produto.price) }}</p> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button | |
| @click="comprarProduto(produto)" | |
| :class="['bg-[#feb702] border text-gray-800 rounded-custom py-3 px-4 rounded border-transparent transition-all', produto.maisVendido ? 'bg-green-500 text-white hover:bg-green-500/80' : 'hover:bg-transparent hover:border-[#feb702] ']" | |
| > | |
| Selecionar | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <button | |
| type="button" | |
| @click="resetar" | |
| class="w-full bg-[#feb702] text-gray-700 max-w-[180px] font-semibold py-2 px-4 rounded-custom mt-10 justify-center flex items-center border-transparent disabled:opacity-70 m-auto disabled:cursor-not-allowed justify-center space-x-2 border-transparent" | |
| > | |
| <span>Fazer nova busca</span> | |
| </button> | |
| </div> | |
| </section> | |
| <script type="module"> | |
| const { createApp, ref, computed } = Vue; | |
| import { initializeApp } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-app.js"; | |
| import { | |
| getFirestore, | |
| collection, | |
| addDoc, | |
| } from "https://www.gstatic.com/firebasejs/11.0.1/firebase-firestore.js"; | |
| const firebaseConfig = { | |
| apiKey: "AIzaSyBL7akcVSjWN8qsJwanGy6xtvuwNGBXdwI", | |
| authDomain: "traqueamento-banco-de-dados.firebaseapp.com", | |
| projectId: "traqueamento-banco-de-dados", | |
| storageBucket: "traqueamento-banco-de-dados.firebasestorage.app", | |
| messagingSenderId: "473439299774", | |
| appId: "1:473439299774:web:c0d38499c04b5c582456ef", | |
| }; | |
| const firebase = initializeApp(firebaseConfig); | |
| const db = getFirestore(firebase); | |
| const collectionData = collection(db, "formulario-leads"); | |
| const urls = { | |
| produto1: "https://pay.kiwify.com.br/QmHq9un", | |
| produto2: "https://pay.kiwify.com.br/HTLhjNS", | |
| produto3: "https://pay.kiwify.com.br/UJ1PoU2", | |
| produto4: "https://pay.kiwify.com.br/3Qt0vAb", | |
| }; | |
| const baseProdutos = [ | |
| { | |
| name: "Pacote 1", | |
| quantity: 500, | |
| price: 77.9, | |
| url: urls.produto1, | |
| maisVendido: false, | |
| }, | |
| { | |
| name: "Pacote 2", | |
| quantity: 1000, | |
| price: 127.9, | |
| url: urls.produto2, | |
| maisVendido: false, | |
| }, | |
| { | |
| name: "Pacote 3", | |
| quantity: 1500, | |
| price: 137.9, | |
| url: urls.produto3, | |
| maisVendido: true, | |
| }, | |
| ]; | |
| const produtoCoringa = { | |
| name: "Pacote 3", | |
| quantity: 5000, | |
| price: 347, | |
| url: urls.produto4, | |
| maisVendido: false, | |
| }; | |
| const app = createApp({ | |
| setup() { | |
| const loadingInicial = ref(true); | |
| const carregandoLeads = ref(false); | |
| const estadoSelecionado = ref(""); | |
| const cidadeSelecionada = ref(""); | |
| const todoBrasil = ref(false); | |
| const todosAsCidades = ref(false); | |
| const estados = ref({ | |
| AC: "Acre", | |
| AL: "Alagoas", | |
| AP: "Amapá", | |
| AM: "Amazonas", | |
| BA: "Bahia", | |
| CE: "Ceará", | |
| DF: "Distrito Federal", | |
| ES: "Espírito Santo", | |
| GO: "Goías", | |
| MA: "Maranhão", | |
| MT: "Mato Grosso", | |
| MS: "Mato Grosso do Sul", | |
| MG: "Minas Gerais", | |
| PA: "Pará", | |
| PB: "Paraíba", | |
| PR: "Paraná", | |
| PE: "Pernambuco", | |
| PI: "Piauí", | |
| RJ: "Rio de Janeiro", | |
| RN: "Rio Grande do Norte", | |
| RS: "Rio Grande do Sul", | |
| RO: "Rondônia", | |
| RR: "Roraíma", | |
| SC: "Santa Catarina", | |
| SP: "São Paulo", | |
| SE: "Sergipe", | |
| TO: "Tocantins", | |
| }); | |
| const cidades = ref([]); | |
| const leadsDisponiveis = ref(0); | |
| const mostrarResultados = ref(false); | |
| const nichosNovosSelecionados = ref([]); | |
| const mostrarOutros = computed(() => | |
| nichosNovosSelecionados.value.includes("Outros") | |
| ); | |
| const nichoCustomizado = ref(""); | |
| const nichos = [ | |
| "Consorcio (Carro, Moto, Imóvel)", | |
| "Plano de Saúde (PJ, PF)", | |
| "FGTS", | |
| "Seguros/Proteção Veicular", | |
| "Direito/Advocacia", | |
| "Empréstimo Consignado", | |
| "Imóveis (Baixo, Médio e Alto Padrão)", | |
| "Produtos e serviços femininos", | |
| "Energia solar", | |
| "B2B/ Empresas", | |
| "Educação/Graduação", | |
| "Clinicas/Consultorios", | |
| "Outros", | |
| ]; | |
| const produtos = ref([]); | |
| const moneyFormat = (numero) => { | |
| return new Intl.NumberFormat("pt-br", { | |
| style: "currency", | |
| currency: "BRL", | |
| }).format(numero); | |
| }; | |
| setTimeout(() => { | |
| loadingInicial.value = false; | |
| }, 1500); | |
| const buscarLeads = (e) => { | |
| carregandoLeads.value = true; | |
| const selectedStateArr = Array.from(estadoSelecionado.value); | |
| const selectedCitiesArr = Array.from(cidadeSelecionada.value); | |
| addDoc(collectionData, { | |
| nichos: Array.from(nichosNovosSelecionados.value), | |
| nichoCustomizado: nichoCustomizado.value, | |
| estadoSelecionado: selectedStateArr, | |
| cidadeSelecionada: selectedCitiesArr, | |
| uid: new Date().getTime(), | |
| criadoEm: new Date(), | |
| }); | |
| setTimeout(() => { | |
| const max = Math.min( | |
| estados.value.length || 6, | |
| Math.max(selectedCitiesArr.length, selectedStateArr.length) | |
| ); | |
| let customData = [...baseProdutos]; | |
| if (todoBrasil.value || todosAsCidades.value) { | |
| customData = [ | |
| ...customData, | |
| { | |
| ...produtoCoringa, | |
| }, | |
| ]; | |
| } | |
| let minLeads = 1667; | |
| let maxLeads = 2420; | |
| // todo o estado | |
| if (todosAsCidades.value) { | |
| minLeads = 6437; | |
| maxLeads = 12349; | |
| } | |
| // todo o brasil | |
| if (todoBrasil.value) { | |
| minLeads = 6437; | |
| maxLeads = 34599; | |
| } | |
| produtos.value = customData; | |
| leadsDisponiveis.value = | |
| Math.floor(Math.random() * (maxLeads - minLeads + 1)) + | |
| minLeads; | |
| mostrarResultados.value = true; | |
| carregandoLeads.value = false; | |
| const allPosForm = document.querySelectorAll("#posform"); | |
| allPosForm.forEach((el) => { | |
| el.classList.add("show"); | |
| }); | |
| }, 7_000); | |
| }; | |
| const comprarProduto = (produto) => { | |
| if (produto.url) window.location.href = produto.url; | |
| }; | |
| const limparCidades = () => { | |
| cidadeSelecionada.value = ""; | |
| }; | |
| const limparEstadosCidade = () => { | |
| limparCidades(); | |
| estadoSelecionado.value = ""; | |
| todosAsCidades.value = false; | |
| }; | |
| const resetar = (produto) => { | |
| limparEstadosCidade(); | |
| nichosNovosSelecionados.value = []; | |
| mostrarOutros.value = false; | |
| nichoCustomizado.value = ""; | |
| mostrarResultados.value = false; | |
| }; | |
| return { | |
| loadingInicial, | |
| estadoSelecionado, | |
| cidadeSelecionada, | |
| estados, | |
| cidades, | |
| leadsDisponiveis, | |
| mostrarResultados, | |
| produtos, | |
| carregandoLeads, | |
| nichos, | |
| todoBrasil, | |
| todosAsCidades, | |
| nichosNovosSelecionados, | |
| mostrarOutros, | |
| nichoCustomizado, | |
| moneyFormat, | |
| limparEstadosCidade, | |
| limparCidades, | |
| buscarLeads, | |
| comprarProduto, | |
| resetar, | |
| }; | |
| }, | |
| }); | |
| app.component("v-select", window["vue-select"]); | |
| app.mount("#app"); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment