-- 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"]}' );