mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-16 21:37:51 +00:00
feat: Criando tabelas para nova funcionalidade de correção de redação
This commit is contained in:
parent
478ca2441d
commit
206f7bcb30
171
supabase/migrations/20240326000001_create_essay_system.sql
Normal file
171
supabase/migrations/20240326000001_create_essay_system.sql
Normal file
@ -0,0 +1,171 @@
|
||||
-- Criação do sistema de redações (Essays)
|
||||
-- Tipos de texto (Narrativo, Dissertativo, etc)
|
||||
CREATE TABLE public.essay_types (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
icon TEXT NOT NULL,
|
||||
active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Gêneros textuais (Artigo de opinião, Carta argumentativa, etc)
|
||||
CREATE TABLE public.essay_genres (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
type_id UUID NOT NULL REFERENCES public.essay_types(id),
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
icon TEXT NOT NULL,
|
||||
requirements JSONB NOT NULL DEFAULT '{}',
|
||||
active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Redações dos alunos
|
||||
CREATE TABLE public.student_essays (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
student_id UUID NOT NULL REFERENCES public.students(id),
|
||||
type_id UUID NOT NULL REFERENCES public.essay_types(id),
|
||||
genre_id UUID NOT NULL REFERENCES public.essay_genres(id),
|
||||
title TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'draft',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
|
||||
CONSTRAINT status_check CHECK (status IN ('draft', 'submitted', 'analyzed'))
|
||||
);
|
||||
|
||||
-- Análises das redações
|
||||
CREATE TABLE public.essay_analyses (
|
||||
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
|
||||
essay_id UUID NOT NULL REFERENCES public.student_essays(id),
|
||||
overall_score INTEGER NOT NULL CHECK (overall_score >= 0 AND overall_score <= 100),
|
||||
feedback JSONB NOT NULL DEFAULT '{}',
|
||||
strengths TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
improvements TEXT[] DEFAULT ARRAY[]::TEXT[],
|
||||
suggestions TEXT,
|
||||
criteria_scores JSONB NOT NULL DEFAULT '{}',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
||||
);
|
||||
|
||||
-- Índices para melhor performance
|
||||
CREATE INDEX idx_student_essays_student_id ON public.student_essays(student_id);
|
||||
CREATE INDEX idx_student_essays_status ON public.student_essays(status);
|
||||
CREATE INDEX idx_essay_genres_type_id ON public.essay_genres(type_id);
|
||||
CREATE INDEX idx_essay_analyses_essay_id ON public.essay_analyses(essay_id);
|
||||
|
||||
-- Triggers para updated_at
|
||||
CREATE OR REPLACE FUNCTION public.handle_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = now();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
CREATE TRIGGER essay_types_updated_at
|
||||
BEFORE UPDATE ON public.essay_types
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.handle_updated_at();
|
||||
|
||||
CREATE TRIGGER essay_genres_updated_at
|
||||
BEFORE UPDATE ON public.essay_genres
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.handle_updated_at();
|
||||
|
||||
CREATE TRIGGER student_essays_updated_at
|
||||
BEFORE UPDATE ON public.student_essays
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE public.handle_updated_at();
|
||||
|
||||
-- Políticas RLS
|
||||
ALTER TABLE public.essay_types ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.essay_genres ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.student_essays ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.essay_analyses ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- Políticas para essay_types (visível para todos)
|
||||
CREATE POLICY "Tipos de redação visíveis para todos"
|
||||
ON public.essay_types FOR SELECT
|
||||
USING (active = true);
|
||||
|
||||
-- Políticas para essay_genres (visível para todos)
|
||||
CREATE POLICY "Gêneros textuais visíveis para todos"
|
||||
ON public.essay_genres FOR SELECT
|
||||
USING (active = true);
|
||||
|
||||
-- Políticas para student_essays
|
||||
CREATE POLICY "Alunos podem ver suas próprias redações"
|
||||
ON public.student_essays FOR SELECT
|
||||
USING (student_id = auth.uid());
|
||||
|
||||
CREATE POLICY "Alunos podem criar suas próprias redações"
|
||||
ON public.student_essays FOR INSERT
|
||||
WITH CHECK (student_id = auth.uid());
|
||||
|
||||
CREATE POLICY "Alunos podem atualizar suas próprias redações"
|
||||
ON public.student_essays FOR UPDATE
|
||||
USING (student_id = auth.uid())
|
||||
WITH CHECK (student_id = auth.uid());
|
||||
|
||||
-- Políticas para essay_analyses
|
||||
CREATE POLICY "Alunos podem ver análises de suas próprias redações"
|
||||
ON public.essay_analyses FOR SELECT
|
||||
USING (
|
||||
essay_id IN (
|
||||
SELECT id FROM public.student_essays
|
||||
WHERE student_id = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- Função para verificar se uma redação pertence ao aluno
|
||||
CREATE OR REPLACE FUNCTION public.check_essay_ownership(essay_id UUID)
|
||||
RETURNS BOOLEAN AS $$
|
||||
BEGIN
|
||||
RETURN EXISTS (
|
||||
SELECT 1
|
||||
FROM public.student_essays
|
||||
WHERE id = essay_id
|
||||
AND student_id = auth.uid()
|
||||
);
|
||||
END;
|
||||
$$ language plpgsql security definer;
|
||||
|
||||
-- Comentários nas tabelas
|
||||
COMMENT ON TABLE public.essay_types IS 'Tipos de texto (Narrativo, Dissertativo, etc)';
|
||||
COMMENT ON TABLE public.essay_genres IS 'Gêneros textuais relacionados a cada tipo de texto';
|
||||
COMMENT ON TABLE public.student_essays IS 'Redações escritas pelos alunos';
|
||||
COMMENT ON TABLE public.essay_analyses IS 'Análises e feedbacks das redações dos alunos';
|
||||
|
||||
-- Dados iniciais
|
||||
INSERT INTO public.essay_types (slug, title, description, icon) VALUES
|
||||
('narrative', 'Narrativo', 'Textos que contam uma história com personagens, tempo e espaço definidos', '📖'),
|
||||
('dissertation', 'Dissertativo', 'Textos que apresentam uma análise e discussão de um tema', '📝'),
|
||||
('descriptive', 'Descritivo', 'Textos que descrevem detalhadamente um objeto, pessoa, lugar ou situação', '🎨');
|
||||
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'dissertation'),
|
||||
'opinion-article',
|
||||
'Artigo de Opinião',
|
||||
'Texto que apresenta um ponto de vista sobre um tema atual',
|
||||
'📰',
|
||||
'{"min_words": 300, "max_words": 600, "required_sections": ["introduction", "development", "conclusion"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'short-story',
|
||||
'Conto',
|
||||
'História curta com poucos personagens e um único conflito',
|
||||
'📚',
|
||||
'{"min_words": 200, "max_words": 1000, "required_elements": ["characters", "setting", "conflict", "resolution"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'descriptive'),
|
||||
'character-description',
|
||||
'Descrição de Personagem',
|
||||
'Texto que descreve características físicas e psicológicas de um personagem',
|
||||
'👤',
|
||||
'{"min_words": 150, "max_words": 400, "required_aspects": ["physical", "psychological", "habits"]}'
|
||||
);
|
||||
@ -0,0 +1,30 @@
|
||||
-- Remover políticas
|
||||
DROP POLICY IF EXISTS "Alunos podem ver análises de suas próprias redações" ON public.essay_analyses;
|
||||
DROP POLICY IF EXISTS "Alunos podem atualizar suas próprias redações" ON public.student_essays;
|
||||
DROP POLICY IF EXISTS "Alunos podem criar suas próprias redações" ON public.student_essays;
|
||||
DROP POLICY IF EXISTS "Alunos podem ver suas próprias redações" ON public.student_essays;
|
||||
DROP POLICY IF EXISTS "Gêneros textuais visíveis para todos" ON public.essay_genres;
|
||||
DROP POLICY IF EXISTS "Tipos de redação visíveis para todos" ON public.essay_types;
|
||||
|
||||
-- Remover função de verificação de propriedade
|
||||
DROP FUNCTION IF EXISTS public.check_essay_ownership(UUID);
|
||||
|
||||
-- Remover triggers
|
||||
DROP TRIGGER IF EXISTS student_essays_updated_at ON public.student_essays;
|
||||
DROP TRIGGER IF EXISTS essay_genres_updated_at ON public.essay_genres;
|
||||
DROP TRIGGER IF EXISTS essay_types_updated_at ON public.essay_types;
|
||||
|
||||
-- Remover função do trigger
|
||||
DROP FUNCTION IF EXISTS public.handle_updated_at();
|
||||
|
||||
-- Remover índices
|
||||
DROP INDEX IF EXISTS public.idx_essay_analyses_essay_id;
|
||||
DROP INDEX IF EXISTS public.idx_essay_genres_type_id;
|
||||
DROP INDEX IF EXISTS public.idx_student_essays_status;
|
||||
DROP INDEX IF EXISTS public.idx_student_essays_student_id;
|
||||
|
||||
-- Remover tabelas
|
||||
DROP TABLE IF EXISTS public.essay_analyses;
|
||||
DROP TABLE IF EXISTS public.student_essays;
|
||||
DROP TABLE IF EXISTS public.essay_genres;
|
||||
DROP TABLE IF EXISTS public.essay_types;
|
||||
141
supabase/migrations/20240326000002_insert_essay_data.sql
Normal file
141
supabase/migrations/20240326000002_insert_essay_data.sql
Normal file
@ -0,0 +1,141 @@
|
||||
-- Inserir tipos textuais
|
||||
INSERT INTO public.essay_types (slug, title, description, icon) VALUES
|
||||
('narrative', 'Narrativo', 'Textos que narram acontecimentos reais ou fictícios, com personagens, tempo e espaço definidos', '📖'),
|
||||
('descriptive', 'Descrição', 'Textos que descrevem detalhadamente características de algo ou alguém', '🎨'),
|
||||
('expository', 'Expositivo', 'Textos que explicam e informam sobre um determinado assunto', '📚'),
|
||||
('argumentative', 'Argumentativo', 'Textos que defendem uma ideia ou ponto de vista com argumentos', '⚖️'),
|
||||
('injunctive', 'Injuntivo', 'Textos que orientam ou instruem sobre como realizar algo', '📝');
|
||||
|
||||
-- Inserir gêneros textuais para tipo Narrativo
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'short-story',
|
||||
'Conto',
|
||||
'História curta com poucos personagens e um único conflito',
|
||||
'📚',
|
||||
'{"min_words": 200, "max_words": 1000, "required_elements": ["personagens", "tempo", "espaço", "conflito", "resolução"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'chronicle',
|
||||
'Crônica',
|
||||
'Narrativa curta que retrata situações do cotidiano',
|
||||
'📰',
|
||||
'{"min_words": 150, "max_words": 800, "required_elements": ["situação_cotidiana", "reflexão", "linguagem_informal"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'novel',
|
||||
'Romance',
|
||||
'História longa com desenvolvimento aprofundado de personagens e tramas',
|
||||
'📖',
|
||||
'{"min_words": 1000, "max_words": 3000, "required_elements": ["personagens_principais", "personagens_secundários", "múltiplos_conflitos", "desenvolvimento_completo"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'news',
|
||||
'Notícia',
|
||||
'Relato de fatos reais de forma objetiva',
|
||||
'📰',
|
||||
'{"min_words": 150, "max_words": 500, "required_elements": ["lead", "corpo_da_notícia", "objetividade"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'narrative'),
|
||||
'biography',
|
||||
'Biografia/Autobiografia',
|
||||
'Relato da vida de uma pessoa',
|
||||
'👤',
|
||||
'{"min_words": 300, "max_words": 1000, "required_elements": ["dados_pessoais", "acontecimentos_importantes", "ordem_cronológica"]}'
|
||||
);
|
||||
|
||||
-- Inserir gêneros textuais para tipo Descritivo
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'descriptive'),
|
||||
'menu',
|
||||
'Cardápio',
|
||||
'Descrição detalhada de pratos e bebidas',
|
||||
'🍽️',
|
||||
'{"min_words": 50, "max_words": 200, "required_elements": ["nome_do_prato", "ingredientes", "preço"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'descriptive'),
|
||||
'descriptive-report',
|
||||
'Relato descritivo',
|
||||
'Descrição detalhada de um objeto, pessoa ou ambiente',
|
||||
'🔍',
|
||||
'{"min_words": 200, "max_words": 600, "required_elements": ["características_físicas", "sensações", "detalhes_específicos"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'descriptive'),
|
||||
'reportage',
|
||||
'Reportagem',
|
||||
'Descrição aprofundada de um fato ou tema',
|
||||
'📰',
|
||||
'{"min_words": 400, "max_words": 1000, "required_elements": ["contextualização", "detalhamento", "fontes"]}'
|
||||
);
|
||||
|
||||
-- Inserir gêneros textuais para tipo Expositivo
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'expository'),
|
||||
'didactic-text',
|
||||
'Texto didático',
|
||||
'Explicação clara de um conteúdo para fins educacionais',
|
||||
'📚',
|
||||
'{"min_words": 200, "max_words": 800, "required_elements": ["definição", "exemplos", "explicação"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'expository'),
|
||||
'lecture',
|
||||
'Palestra',
|
||||
'Apresentação expositiva sobre um tema específico',
|
||||
'🎤',
|
||||
'{"min_words": 500, "max_words": 1500, "required_elements": ["introdução", "desenvolvimento", "conclusão", "exemplos_práticos"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'expository'),
|
||||
'reportage-exp',
|
||||
'Reportagem',
|
||||
'Texto informativo sobre um tema ou acontecimento',
|
||||
'📰',
|
||||
'{"min_words": 400, "max_words": 1000, "required_elements": ["contextualização", "dados", "fontes"]}'
|
||||
);
|
||||
|
||||
-- Inserir gêneros textuais para tipo Argumentativo
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'argumentative'),
|
||||
'open-letter',
|
||||
'Carta aberta',
|
||||
'Texto que expõe publicamente argumentos sobre uma questão',
|
||||
'✉️',
|
||||
'{"min_words": 300, "max_words": 800, "required_elements": ["destinatário", "argumentos", "pedido_ou_reivindicação"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'argumentative'),
|
||||
'thesis',
|
||||
'Tese',
|
||||
'Texto que defende uma ideia central com argumentos',
|
||||
'📑',
|
||||
'{"min_words": 500, "max_words": 1500, "required_elements": ["hipótese", "argumentos", "comprovação"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'argumentative'),
|
||||
'scientific-article',
|
||||
'Artigo científico',
|
||||
'Texto que apresenta resultados de uma pesquisa',
|
||||
'🔬',
|
||||
'{"min_words": 1000, "max_words": 3000, "required_elements": ["introdução", "metodologia", "resultados", "conclusão"]}'
|
||||
);
|
||||
|
||||
-- Inserir gêneros textuais para tipo Injuntivo
|
||||
INSERT INTO public.essay_genres (type_id, slug, title, description, icon, requirements) VALUES
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'injunctive'),
|
||||
'instruction-manual',
|
||||
'Manual de instrução',
|
||||
'Texto que orienta sobre o uso de um produto',
|
||||
'📖',
|
||||
'{"min_words": 100, "max_words": 500, "required_elements": ["passo_a_passo", "advertências", "ilustrações"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'injunctive'),
|
||||
'advertisement',
|
||||
'Propaganda',
|
||||
'Texto que persuade o leitor a uma ação',
|
||||
'📢',
|
||||
'{"min_words": 50, "max_words": 200, "required_elements": ["slogan", "argumentos_persuasivos", "chamada_para_ação"]}'
|
||||
),
|
||||
((SELECT id FROM public.essay_types WHERE slug = 'injunctive'),
|
||||
'recipe',
|
||||
'Receita',
|
||||
'Texto que instrui o preparo de um prato',
|
||||
'👩🍳',
|
||||
'{"min_words": 100, "max_words": 400, "required_elements": ["ingredientes", "modo_de_preparo", "tempo_de_preparo", "rendimento"]}'
|
||||
);
|
||||
Loading…
Reference in New Issue
Block a user