Initial commit: MetisClass - Plataforma Educacional

This commit is contained in:
bigtux
2026-02-10 15:46:24 -03:00
commit 52a2bc8fe1
60 changed files with 14300 additions and 0 deletions

View File

@@ -0,0 +1,145 @@
import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth";
import { authOptions } from "@/lib/auth";
import prisma from "@/lib/prisma";
import { generateWithGemini } from "@/lib/gemini";
const GENERATION_PROMPTS = {
LESSON_PLAN: `Você é um especialista em educação brasileira. Crie um plano de aula completo e detalhado seguindo a estrutura abaixo:
## Dados da Aula
- **Disciplina:** {subject}
- **Ano/Série:** {grade}
- **Tema:** {topic}
- **Duração:** {duration}
## Estrutura do Plano
### 1. Objetivos de Aprendizagem
- Objetivo geral
- Objetivos específicos (3-5)
- Competências da BNCC relacionadas
### 2. Conteúdos
- Conceituais
- Procedimentais
- Atitudinais
### 3. Metodologia
- Abordagem pedagógica
- Estratégias de ensino
- Recursos didáticos necessários
### 4. Desenvolvimento da Aula
- Momento inicial (aquecimento/motivação)
- Desenvolvimento (atividades principais)
- Fechamento (síntese/avaliação)
### 5. Avaliação
- Critérios de avaliação
- Instrumentos avaliativos
- Indicadores de aprendizagem
### 6. Referências e Materiais de Apoio
Seja detalhado, prático e alinhado às diretrizes da BNCC. Use linguagem clara e objetiva.`,
EXAM: `Você é um especialista em avaliação educacional. Crie uma prova/lista de exercícios seguindo os parâmetros:
- **Disciplina:** {subject}
- **Ano/Série:** {grade}
- **Tema:** {topic}
- **Número de questões:** {questionCount}
- **Tipos de questões:** {questionTypes}
- **Nível de dificuldade:** {difficulty}
Para cada questão, inclua:
- Enunciado claro e objetivo
- Alternativas (se múltipla escolha)
- Gabarito
- Habilidade BNCC relacionada
Varie os tipos de questões e níveis de dificuldade progressivamente.`,
};
export async function POST(request: NextRequest) {
try {
const session = await getServerSession(authOptions);
if (!session?.user?.id) {
return NextResponse.json({ error: "Não autorizado" }, { status: 401 });
}
const user = await prisma.user.findUnique({
where: { id: session.user.id },
select: { credits: true, plan: true },
});
if (!user) {
return NextResponse.json({ error: "Usuário não encontrado" }, { status: 404 });
}
if (user.credits <= 0 && user.plan === "FREE") {
return NextResponse.json(
{ error: "Créditos insuficientes. Faça upgrade para continuar." },
{ status: 403 }
);
}
const body = await request.json();
const { type, ...params } = body;
if (!type || !GENERATION_PROMPTS[type as keyof typeof GENERATION_PROMPTS]) {
return NextResponse.json({ error: "Tipo de geração inválido" }, { status: 400 });
}
// Build prompt
let prompt = GENERATION_PROMPTS[type as keyof typeof GENERATION_PROMPTS];
Object.entries(params).forEach(([key, value]) => {
prompt = prompt.replace(`{${key}}`, value as string);
});
// Call Gemini API
const content = await generateWithGemini(
prompt,
"Você é um assistente especializado em educação brasileira, ajudando professores a criar conteúdos pedagógicos de alta qualidade."
);
if (!content) {
throw new Error("Resposta vazia da IA");
}
// Save generation
const generation = await prisma.generation.create({
data: {
userId: session.user.id,
type: type as any,
title: params.topic || params.title || "Sem título",
content: { text: content },
prompt: prompt,
model: "gemini-2.0-flash",
tokens: 0,
},
});
// Deduct credits (only for FREE plan)
if (user.plan === "FREE") {
await prisma.user.update({
where: { id: session.user.id },
data: { credits: { decrement: 1 } },
});
}
return NextResponse.json({
id: generation.id,
content: content,
tokens: 0,
});
} catch (error: any) {
console.error("Generation error:", error);
return NextResponse.json(
{ error: error.message || "Erro ao gerar conteúdo" },
{ status: 500 }
);
}
}