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:
parent
1d22b504a0
commit
c323023e28
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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}>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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());
|
||||
Loading…
Reference in New Issue
Block a user