📻 RADIO BLOG
Pronto

Página online

 

Mensagem Completa para o Programador (Parte 01)

​Assunto: Integração Módulo de Autenticação, Trial e Pagamento — ROTAFÁCIL GPS (Parte 01)

​Olá! Segue abaixo o contexto do projeto, a estrutura base e a lógica da Parte 01 do nosso sistema (ROTAFÁCIL GPS).

​1. Contexto do Projeto & Integração das Partes

​Nosso sistema está dividido em duas partes/módulos independentes que serão unificados:

  • ​Parte 01 (Sua parte): Autenticação de usuários, controle do trial de 15 dias, gestão de assinaturas/bloqueio via InfinitePay e controle de sessão/dispositivos.
  • ​Parte 02 (Desenvolvida em paralelo): O aplicativo do Roteirizador com GPS, navegação e manipulação de endereços.

​Seu Objetivo de Integração: O seu código (Parte 01) deve atuar como a "camada de entrada e proteção" do sistema. Após o usuário fazer o login e ter o acesso validado (por estar no trial ou com a mensalidade em dia), ele deve ter o acesso liberado para a Parte 02 (o roteirizador).

​2. Regras de Negócio e Diretrizes

  • ​Branding: ROTAFÁCIL GPS — "De um entregador para entregadores. Simples e fácil de usar."
  • ​Link de Pagamento (InfinitePay): [https://invoice.infinitepay.io/alexandre-morche/ITaZ64Sot8](https://invoice.infinitepay.io/alexandre-morche/ITaZ64Sot8)
  • ​Valor da Assinatura: R$ 25,00 / mês.
  • ​Período de Teste (Trial): Todo novo usuário cadastrado ganha 15 dias grátis a partir da data de criação da conta no banco de dados.

​Sincronização e Regra de Dispositivos:

  • ​Até 2 Dispositivos por Conta: A mesma conta pode estar logada em até 2 dispositivos (ex: celular do entregador no suporte e um segundo aparelho/tablet).
  • ​Sincronização de Lista de Endereços: O usuário precisa conseguir cadastrar/carregar a lista de endereços em um celular e ter essa mesma lista atualizada e pronta para navegação na "rota atual" do outro celular (via banco de dados / Supabase Realtime).
  • ​Trava de Navegação Ativa: Embora permita 2 aparelhos logados para carga de dados, a navegação ativa no GPS/rota deve funcionar em apenas 1 dispositivo por vez.

​3. Lógica de Validação e Bloqueio

​O fluxo da Parte 01 deve consultar no Supabase se:

  1. ​O usuário está dentro do prazo de 15 dias grátis (data_criacao + 15 dias >= data_atual); OU
  2. ​O usuário possui uma assinatura paga ativa (pago_ate >= data_atual).
  • ​Se SIM: Concede permissão e redireciona/carrega a interface do Roteirizador (Parte 02).
  • ​Se NÃO (Expirou): Oculta a interface principal e exibe a tela de bloqueio com o aviso de vencimento e o botão para pagamento de R$ 25,00 apontando para o link da InfinitePay.

​4. Código Base de Referência (index.html)

​Você pode usar a estrutura abaixo como ponto de partida para integrar com o Supabase:

 

Código Base da Parte 01 (index.html)

<!DOCTYPE html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ROTAFÁCIL GPS - Login & Acesso</title>
  <!-- Supabase JS Client -->
  <script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
  <style>
    :root {
      --bg-color: #121212;
      --card-bg: #1e1e1e;
      --primary: #22c55e;
      --primary-hover: #16a34a;
      --text: #ffffff;
      --text-muted: #a1a1aa;
      --danger: #ef4444;
    }

    * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
    body { background-color: var(--bg-color); color: var(--text); display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 20px; }
    
    .container { background-color: var(--card-bg); width: 100%; max-width: 400px; padding: 30px; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.5); text-align: center; }
    .logo { font-size: 24px; font-weight: bold; color: var(--primary); margin-bottom: 8px; }
    .slogan { font-size: 13px; color: var(--text-muted); margin-bottom: 24px; }
    
    .input-group { margin-bottom: 16px; text-align: left; }
    .input-group label { display: block; font-size: 12px; color: var(--text-muted); margin-bottom: 6px; }
    .input-group input { width: 100%; padding: 12px; border-radius: 6px; border: 1px solid #333; background: #2a2a2a; color: var(--text); outline: none; }
    .input-group input:focus { border-color: var(--primary); }
    
    .btn { width: 100%; padding: 12px; border: none; border-radius: 6px; background-color: var(--primary); color: #000; font-weight: bold; cursor: pointer; transition: 0.2s; font-size: 15px; }
    .btn:hover { background-color: var(--primary-hover); }
    .btn-pay { background-color: #3b82f6; color: white; text-decoration: none; display: block; text-align: center; margin-top: 15px; }
    .btn-pay:hover { background-color: #2563eb; }
    
    .hidden { display: none; }
    .status-box { padding: 12px; border-radius: 6px; margin-bottom: 16px; font-size: 14px; }
    .status-expired { background-color: rgba(239, 68, 68, 0.1); border: 1px solid var(--danger); color: var(--danger); }
  </style>
</head>
<body>

  <div class="container" id="auth-card">
    <div class="logo">ROTAFÁCIL GPS</div>
    <div class="slogan">De um entregador para entregadores. Simples e fácil de usar.</div>

    <!-- TELA DE LOGIN / REGISTO -->
    <form id="login-form">
      <div class="input-group">
        <label for="email">E-mail</label>
        <input type="email" id="email" placeholder="seu@email.com" required>
      </div>
      <div class="input-group">
        <label for="password">Senha</label>
        <input type="password" id="password" placeholder="******" required>
      </div>
      <button type="submit" class="btn">Entrar / Cadastrar</button>
    </form>

    <!-- TELA DE BLOQUEIO DE PAGAMENTO (EXIBIDA SE TRIAL/MENSALIDADE EXPIRAR) -->
    <div id="payment-screen" class="hidden">
      <div class="status-box status-expired">
        Seu período de teste ou assinatura expirou!
      </div>
      <p style="font-size: 14px; color: var(--text-muted); margin-bottom: 15px;">
        Para continuar utilizando o ROTAFÁCIL GPS por +30 dias, realize a renovação de R$ 25,00.
      </p>
      <a href="https://invoice.infinitepay.io/alexandre-morche/ITaZ64Sot8" target="_blank" class="btn btn-pay">
        Pagar R$ 25,00 via InfinitePay
      </a>
    </div>
  </div>

  <script>
    // 1. CONFIGURAÇÃO SUPABASE (O programador deve preencher as chaves)
    const SUPABASE_URL = 'https://SEU-PROJETO.supabase.co';
    const SUPABASE_ANON_KEY = 'SUA-CHAVE-ANONIMA';
    const supabase = supabase.createClient(SUPABASE_URL, SUPABASE_ANON_KEY);

    const loginForm = document.getElementById('login-form');
    const paymentScreen = document.getElementById('payment-screen');

    // 2. LÓGICA DE VALIDAÇÃO DE ACESSO E TRIAL
    async function checkUserAccess(user) {
      let { data: profile, error } = await supabase
        .from('profiles')
        .select('created_at, pago_ate')
        .eq('id', user.id)
        .single();

      if (error || !profile) return false;

      const now = new Date();
      const createdAt = new Date(profile.created_at);
      const trialEndDate = new Date(createdAt);
      trialEndDate.setDate(trialEndDate.getDate() + 15); // +15 Dias de Trial

      const paidUntil = profile.pago_ate ? new Date(profile.pago_ate) : null;

      // Valida se está no Trial OU se a Assinatura está Paga
      const isTrialValid = now <= trialEndDate;
      const isSubscriptionValid = paidUntil && now <= paidUntil;

      if (isTrialValid || isSubscriptionValid) {
        // PERMISSÃO CONCEDIDA: Redireciona para a Parte 02 (Roteirizador)
        // A rota ativa e a lista de endereços devem sincronizar via banco de dados Supabase
        window.location.href = 'roteirizador.html'; 
      } else {
        // MENSALIDADE OU TRIAL VENCIDO: Exibe ecrã de pagamento
        loginForm.classList.add('hidden');
        paymentScreen.classList.remove('hidden');
      }
    }

    // 3. SUBMIT DO FORMULÁRIO (LOGIN / AUTOCADASTRO)
    loginForm.addEventListener('submit', async (e) => {
      e.preventDefault();
      const email = document.getElementById('email').value;
      const password = document.getElementById('password').value;

      // Tenta Fazer Login
      let { data, error } = await supabase.auth.signInWithPassword({ email, password });

      // Se o utilizador não existir, cria o registo automaticamente com os 15 dias grátis
      if (error) {
        const signUp = await supabase.auth.signUp({ email, password });
        if (signUp.error) {
          alert('Erro na autenticação: ' + signUp.error.message);
          return;
        }
        data = signUp.data;
      }

      if (data.user) {
        checkUserAccess(data.user);
      }
    });
  </script>
</body>
</html>

Imagem da parte 01:


Comentários