Run SQL to create tables and policies

This commit executes the provided SQL script to create the necessary tables (`faqs`, `faq_feedback`, `contatos`) and associated policies for the help system, as reviewed by the user. It also creates a storage bucket for contact form attachments.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-21 19:44:53 +00:00
parent 1d22b504a0
commit c323023e28
6 changed files with 180 additions and 14 deletions

View File

@ -75,7 +75,7 @@ const ContactForm = ({ onBack }: ContactFormProps) => {
// Salvar contato no banco
const { error } = await supabase
.from('contatos')
.from('contatos' as any)
.insert({
assunto: formData.assunto,
motivo: formData.motivo,

View File

@ -29,13 +29,13 @@ const FAQList = () => {
const loadFAQs = async () => {
try {
const { data, error } = await supabase
.from('faqs')
.from('faqs' as any)
.select('*')
.eq('ativo', true)
.order('created_at', { ascending: false });
if (error) throw error;
setFaqs(data || []);
setFaqs((data as FAQ[]) || []);
} catch (error) {
console.error('Erro ao carregar FAQs:', error);
toast({
@ -61,7 +61,7 @@ const FAQList = () => {
const handleFeedback = async (faqId: string, helpful: boolean) => {
try {
const { error } = await supabase
.from('faq_feedback')
.from('faq_feedback' as any)
.insert({
faq_id: faqId,
helpful: helpful,

View File

@ -20,10 +20,11 @@ const HelpIcon = () => {
<Button
variant="outline"
size="icon"
className="fixed bottom-6 right-6 h-14 w-14 rounded-full shadow-lg hover:shadow-xl transition-all z-50 bg-blue-600 text-white hover:bg-blue-700 border-0"
className="fixed bottom-6 right-6 h-16 w-16 rounded-full shadow-lg hover:shadow-xl transition-all z-50 bg-blue-600 text-white hover:bg-blue-700 border-0 flex flex-col items-center justify-center p-2"
onClick={() => setIsOpen(true)}
>
<HelpCircle className="h-6 w-6" />
<HelpCircle className="h-6 w-6 mb-1" />
<span className="text-xs font-medium">Ajuda</span>
</Button>
<Dialog open={isOpen} onOpenChange={setIsOpen}>

View File

@ -159,6 +159,39 @@ export type Database = {
}
Relationships: []
}
contatos: {
Row: {
anexo_url: string | null
assunto: string
created_at: string
id: string
mensagem: string
motivo: string
status: string
user_id: string | null
}
Insert: {
anexo_url?: string | null
assunto: string
created_at?: string
id?: string
mensagem: string
motivo: string
status?: string
user_id?: string | null
}
Update: {
anexo_url?: string | null
assunto?: string
created_at?: string
id?: string
mensagem?: string
motivo?: string
status?: string
user_id?: string | null
}
Relationships: []
}
conversas_zap: {
Row: {
created_at: string
@ -264,6 +297,65 @@ export type Database = {
},
]
}
faq_feedback: {
Row: {
created_at: string
faq_id: string
helpful: boolean
id: string
user_id: string | null
}
Insert: {
created_at?: string
faq_id: string
helpful: boolean
id?: string
user_id?: string | null
}
Update: {
created_at?: string
faq_id?: string
helpful?: boolean
id?: string
user_id?: string | null
}
Relationships: [
{
foreignKeyName: "faq_feedback_faq_id_fkey"
columns: ["faq_id"]
isOneToOne: false
referencedRelation: "faqs"
referencedColumns: ["id"]
},
]
}
faqs: {
Row: {
ativo: boolean
created_at: string
id: string
imagem_url: string | null
pergunta: string
resposta: string
}
Insert: {
ativo?: boolean
created_at?: string
id?: string
imagem_url?: string | null
pergunta: string
resposta: string
}
Update: {
ativo?: boolean
created_at?: string
id?: string
imagem_url?: string | null
pergunta?: string
resposta?: string
}
Relationships: []
}
faturas_cartao: {
Row: {
ano: number

View File

@ -57,12 +57,12 @@ const AdminFAQ = () => {
const loadFAQs = async () => {
try {
const { data, error } = await supabase
.from('faqs')
.from('faqs' as any)
.select('*')
.order('created_at', { ascending: false });
if (error) throw error;
setFaqs(data || []);
setFaqs((data as FAQ[]) || []);
} catch (error) {
console.error('Erro ao carregar FAQs:', error);
toast({
@ -78,7 +78,7 @@ const AdminFAQ = () => {
const loadStats = async () => {
try {
const { data, error } = await supabase
.from('faq_feedback')
.from('faq_feedback' as any)
.select(`
faq_id,
helpful,
@ -128,7 +128,7 @@ const AdminFAQ = () => {
try {
if (editingFaq) {
const { error } = await supabase
.from('faqs')
.from('faqs' as any)
.update(formData)
.eq('id', editingFaq.id);
@ -136,7 +136,7 @@ const AdminFAQ = () => {
toast({ title: "FAQ atualizado com sucesso!" });
} else {
const { error } = await supabase
.from('faqs')
.from('faqs' as any)
.insert(formData);
if (error) throw error;
@ -171,7 +171,7 @@ const AdminFAQ = () => {
try {
const { error } = await supabase
.from('faqs')
.from('faqs' as any)
.delete()
.eq('id', id);
@ -191,7 +191,7 @@ const AdminFAQ = () => {
const handleToggleActive = async (id: string, ativo: boolean) => {
try {
const { error } = await supabase
.from('faqs')
.from('faqs' as any)
.update({ ativo: !ativo })
.eq('id', id);
@ -251,7 +251,7 @@ const AdminFAQ = () => {
<div className="truncate">{faq.pergunta}</div>
</TableCell>
<TableCell>
<Badge variant={faq.ativo ? "success" : "secondary"}>
<Badge variant={faq.ativo ? "default" : "secondary"}>
{faq.ativo ? 'Ativo' : 'Inativo'}
</Badge>
</TableCell>

View File

@ -0,0 +1,73 @@
-- Criar tabela para FAQs (Perguntas Frequentes)
CREATE TABLE public.faqs (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
pergunta TEXT NOT NULL,
resposta TEXT NOT NULL,
imagem_url TEXT,
ativo BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);
-- Criar tabela para feedback dos FAQs
CREATE TABLE public.faq_feedback (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
faq_id UUID NOT NULL REFERENCES public.faqs(id) ON DELETE CASCADE,
helpful BOOLEAN NOT NULL,
user_id UUID REFERENCES auth.users(id),
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);
-- Criar tabela para contatos/mensagens de suporte
CREATE TABLE public.contatos (
id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY,
user_id UUID REFERENCES auth.users(id),
assunto TEXT NOT NULL,
motivo TEXT NOT NULL,
mensagem TEXT NOT NULL,
anexo_url TEXT,
status TEXT NOT NULL DEFAULT 'pendente',
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()
);
-- Criar bucket para anexos de contato
INSERT INTO storage.buckets (id, name, public)
VALUES ('anexos-contato', 'anexos-contato', true);
-- Política para permitir upload de anexos pelos usuários autenticados
CREATE POLICY "Usuarios podem fazer upload de anexos"
ON storage.objects FOR INSERT
WITH CHECK (bucket_id = 'anexos-contato' AND auth.role() = 'authenticated');
-- Política para permitir visualização pública dos anexos
CREATE POLICY "Anexos são públicos para visualização"
ON storage.objects FOR SELECT
USING (bucket_id = 'anexos-contato');
-- Habilitar RLS nas tabelas
ALTER TABLE public.faqs ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.faq_feedback ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.contatos ENABLE ROW LEVEL SECURITY;
-- Políticas para FAQs (todos podem ver FAQs ativos)
CREATE POLICY "Qualquer um pode ver FAQs ativos"
ON public.faqs FOR SELECT
USING (ativo = true);
-- Políticas para feedback (usuários autenticados podem dar feedback)
CREATE POLICY "Usuarios autenticados podem dar feedback"
ON public.faq_feedback FOR INSERT
WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Usuarios podem ver feedbacks"
ON public.faq_feedback FOR SELECT
USING (true);
-- Políticas para contatos (usuários podem criar e ver seus próprios contatos)
CREATE POLICY "Usuarios podem criar contatos"
ON public.contatos FOR INSERT
WITH CHECK (auth.role() = 'authenticated');
CREATE POLICY "Usuarios podem ver seus contatos"
ON public.contatos FOR SELECT
USING (user_id = auth.uid());