From b0bbce26375c2f57bb3bcdb64ddb6347a5665f00 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 15 Jun 2025 21:54:18 +0000 Subject: [PATCH] Add permanent access feature - Added a boolean field `liberado_permanente` to the `usuarios` table. - Updated the RLS policy to allow inserts if `liberado_permanente` is true. - Updated the frontend to show a custom message if the insert is blocked. --- src/hooks/useAccessControl.ts | 34 ++++++++++++++++--- src/integrations/supabase/types.ts | 3 ++ src/pages/Transacoes.tsx | 17 +++++++--- ...9-c97a32c2-8807-4aa2-b8c3-bcd1b25efa96.sql | 29 ++++++++++++++++ 4 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 supabase/migrations/20250615215349-c97a32c2-8807-4aa2-b8c3-bcd1b25efa96.sql diff --git a/src/hooks/useAccessControl.ts b/src/hooks/useAccessControl.ts index ab06e57..f8d0a8d 100644 --- a/src/hooks/useAccessControl.ts +++ b/src/hooks/useAccessControl.ts @@ -8,6 +8,7 @@ interface AccessControlResult { motivo: string | null; // mensagem para exibir ao usuário se bloqueado diasRestantesTrial: number; trialExpiraEm: Date | null; + adminLiberou: boolean; } export function useAccessControl(): AccessControlResult { @@ -17,6 +18,7 @@ export function useAccessControl(): AccessControlResult { motivo: null, diasRestantesTrial: 0, trialExpiraEm: null, + adminLiberou: false, }); useEffect(() => { @@ -29,14 +31,15 @@ export function useAccessControl(): AccessControlResult { motivo: "Erro ao identificar usuário. Faça login novamente.", diasRestantesTrial: 0, trialExpiraEm: null, + adminLiberou: false, }); return; } - // Buscar data de cadastro do usuário + // Buscar data de cadastro e liberado_permanente do usuário const { data: usuarios, error: userError } = await supabase .from("usuarios") - .select("created_at") + .select("created_at, liberado_permanente") .eq("email", userEmail.trim().toLowerCase()); if (userError || !usuarios || usuarios.length === 0) { @@ -46,6 +49,7 @@ export function useAccessControl(): AccessControlResult { motivo: "Erro ao buscar dados do usuário. Tente novamente mais tarde.", diasRestantesTrial: 0, trialExpiraEm: null, + adminLiberou: false, }); return; } @@ -56,6 +60,19 @@ export function useAccessControl(): AccessControlResult { trialExpiraEm.setDate(trialExpiraEm.getDate() + 30); const dentroTrial = agora < trialExpiraEm; const diasRestantes = Math.ceil((trialExpiraEm.getTime() - agora.getTime()) / (1000 * 60 * 60 * 24)); + const liberadoPermanente = usuarios[0].liberado_permanente === true; + + if (liberadoPermanente) { + setResult({ + loading: false, + podeAdicionarTransacao: true, + motivo: "Seu acesso foi liberado permanentemente pelo administrador.", + diasRestantesTrial: 0, + trialExpiraEm, + adminLiberou: true, + }); + return; + } if (dentroTrial) { setResult({ @@ -64,6 +81,7 @@ export function useAccessControl(): AccessControlResult { motivo: null, diasRestantesTrial: diasRestantes, trialExpiraEm, + adminLiberou: false, }); return; } @@ -82,17 +100,24 @@ export function useAccessControl(): AccessControlResult { motivo: "Erro ao verificar status de pagamento.", diasRestantesTrial: 0, trialExpiraEm, + adminLiberou: false, }); return; } - if (pagamentos && pagamentos.length > 0) { + const pagamentoMesVigente = pagamentos && pagamentos.some((p: any) => { + const pgDate = new Date(p.created_at); + return pgDate.getFullYear() === agora.getFullYear() && pgDate.getMonth() === agora.getMonth(); + }); + + if (pagamentoMesVigente) { setResult({ loading: false, podeAdicionarTransacao: true, motivo: null, diasRestantesTrial: 0, trialExpiraEm, + adminLiberou: false, }); return; } @@ -101,9 +126,10 @@ export function useAccessControl(): AccessControlResult { loading: false, podeAdicionarTransacao: false, motivo: - "Seu período de teste acabou. Para continuar adicionando transações realize o pagamento da assinatura.", + "Seu período de teste acabou. Para continuar adicionando transações, realize o pagamento da assinatura.", diasRestantesTrial: 0, trialExpiraEm, + adminLiberou: false, }); } diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 771e22c..4bd755e 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -506,6 +506,7 @@ export type Database = { empresa: string | null id: string instancia_zap: string | null + liberado_permanente: boolean | null nome: string | null remote_jid: string | null status_instancia: string | null @@ -518,6 +519,7 @@ export type Database = { empresa?: string | null id?: string instancia_zap?: string | null + liberado_permanente?: boolean | null nome?: string | null remote_jid?: string | null status_instancia?: string | null @@ -530,6 +532,7 @@ export type Database = { empresa?: string | null id?: string instancia_zap?: string | null + liberado_permanente?: boolean | null nome?: string | null remote_jid?: string | null status_instancia?: string | null diff --git a/src/pages/Transacoes.tsx b/src/pages/Transacoes.tsx index 8799aed..f092c77 100644 --- a/src/pages/Transacoes.tsx +++ b/src/pages/Transacoes.tsx @@ -1,3 +1,4 @@ + import React, { useState } from 'react'; import Layout from '@/components/layout/Layout'; import TransactionsTable from '@/components/dashboard/TransactionsTable'; @@ -61,10 +62,17 @@ const TransacoesPage = () => {
Dados de: {formatMonthDisplay(selectedMonth)}
- {!access.loading && access.podeAdicionarTransacao && access.diasRestantesTrial > 0 && ( -