O TIVIT Academy é uma plataforma completa de gestão educacional desenvolvida com tecnologias modernas e escaláveis. O sistema suporta múltiplos perfis de usuário (Aluno, Professor, Administrador) com funcionalidades específicas para cada grupo, incluindo matrícula, gestão de notas, controle de frequência, distribuição de conteúdo e análise de desempenho.
Stack Técnico:
┌─────────────────────────────────────────────────────────┐
│ TIVIT ACADEMY │
├─────────────────────────────────────────────────────────┤
│ FRONTEND (React + TypeScript + Vite) │
│ - Pages (Dashboards por perfil) │
│ - Components (UI Reutilizável) │
│ - Context API (Autenticação Global) │
│ - Services (Integração API) │
│ - Hooks (Lógica Customizada) │
├─────────────────────────────────────────────────────────┤
│ REST API (ASP.NET Core 9) │
│ - 13 Controllers REST │
│ - 11+ Services (Business Logic) │
│ - 27 DTOs (Data Transfer) │
│ - Exception Middleware │
├─────────────────────────────────────────────────────────┤
│ DATA ACCESS (Entity Framework Core) │
│ - 15 Models (Entities) │
│ - AppDbContext │
│ - Code First Migrations │
│ - SQL Server Database │
├─────────────────────────────────────────────────────────┤
│ INFRASTRUCTURE │
│ - AWS SQS (Message Queue) │
│ - QuestPDF (Report Generation) │
│ - JWT Token Service │
└─────────────────────────────────────────────────────────┘
Controllers (13 total):
Services (11+ total):
Models (15 total):
1. Candidato preenche: Nome, Email, CPF, Curso
↓
2. Backend valida CPF duplicado (mesmo curso)
↓
3. Cria Matricula com Status: AGUARDANDO_PAGAMENTO
↓
4. Candidato envia Comprovante de Pagamento
Status → AGUARDANDO_DOCUMENTOS
↓
5. Candidato envia: Histórico + Cópia CPF
Status → AGUARDANDO_APROVACAO
↓
6. Admin visualiza em /admin/solicitacoes
↓
7. Admin aprova:
- Gera senha aleatória segura (12 chars)
- Hash BCrypt
- Cria Aluno vinculado à Matricula
- Status → APROVADO
- Envia evento para AWS SQS
↓
8. Serviço externo (Lambda/Worker) consome SQS
Envia email com credenciais de acesso
↓
9. Novo aluno recebe email e faz login
CPF + Senha temporária
↓
10. Aluno acessa dashboard
Pode visualizar matérias, notas, eventos
Cálculo:
Media = (Nota1 + Nota2) / 2
Status_Aprovacao:
if QtdFaltas > 10:
Status = "REPROVADO"
else if Media >= 6:
Status = "APROVADO"
else:
Status = "REPROVADO"
Nivel_Desempenho:
if Media < 6:
Nivel = "BRONZE"
else if 6 <= Media <= 8:
Nivel = "PRATA"
else if Media > 8:
Nivel = "OURO"
Constraints:
Regras:
Fluxo:
Autenticação:
POST /api/login
Input: { Tipo, Cpf, Senha }
Output: { id, nome, tipo, token, cursosIds, turmaId }
Matrícula:
POST /api/matricula - Criar (Public)
GET /api/matricula/pendentes - Listar (Admin/Prof)
POST /api/matricula/{id}/pagamento - Upload comprovante (Public)
POST /api/matricula/{id}/documentos - Upload docs (Public)
POST /api/matricula/aprovar/{id} - Aprovar (Admin)
POST /api/matricula/rejeitar/{id} - Rejeitar (Admin)
Notas:
POST /api/nota - Adicionar (Admin/Prof)
GET /api/nota/aluno/{alunoId} - Ver notas (Aluno)
GET /api/nota/desempenho/{alunoId} - Desempenho (Aluno)
GET /api/nota/relatorio/{alunoId} - PDF (Aluno)
Chamada:
POST /api/chamada/realizar - Primeira chamada do dia (Prof)
PUT /api/chamada/atualizar - Atualizar chamada (Prof)
Outros Controllers:
Turma, Materia, Curso, Professor, Aluno, Evento, Conteudo, Notificacao
Autenticação JWT:
Hash de Senha:
Validação de Entrada:
Exception Handling:
Quando usado:
Classe SQSProducer:
public async Task EnviarEventoAsync<T>(T evento)
{
var message = new SendMessageRequest
{
QueueUrl = _queueUrl,
MessageBody = JsonConvert.SerializeObject(evento)
};
await _sqs.SendMessageAsync(message);
}
Páginas:
Componentes Reutilizáveis:
Layouts:
AuthContext armazena:
interface AuthContextType {
user: LoginResponse | null;
token: string | null;
isLoading: boolean;
login: (credentials) => Promise<void>;
logout: () => void;
}
localStorage:
usuarioLogado: JSON com id, nome, tipo, cursosIds, turmaIdtoken: JWT tokenPrivateRoute:
api.ts - Configuração Axios:
auth.service.ts:
export async function login(credentials: LoginCredentials)
export async function logout()
aluno.service.ts:
export async function fetchMateriasAluno(cursoId: number)
export async function fetchDesempenhoAluno(alunoId: number)
export async function fetchAllNotas(alunoId: number)
useAluno.ts:
export function useMateriasAluno(cursoId: number | undefined)
export function useDesempenhoAluno(alunoId: number | undefined)
export function useNotasAluno(alunoId: number | undefined)
Usa React Query para:
useErrorHandler.ts:
export function useErrorHandler()
export function useNotification()
// Login
export const LoginCredentialsSchema = z.object({
Tipo: z.enum(['aluno', 'professor', 'administrador']),
Cpf: z.string().min(11),
Senha: z.string().min(1),
});
// Matrícula
export const EnrollmentDataSchema = z.object({
nome: z.string().min(1),
email: z.string().email(),
cpf: z.string().min(11),
cursoId: z.number(),
});
Públicas:
Aluno (Privadas):
Professor (Privadas):
Admin (Privadas):
Usuários:
Académico:
Notificações:
Matrícula:
Eventos:
Aluno:
Matricula:
Nota:
Chamada:
Usar Entity Framework CLI:
# Criar database
dotnet ef database create
# Ver status
dotnet ef migrations list
# Atualizar
dotnet ef database update
# Adicionar nova migration
dotnet ef migrations add [NomeMigracao]
# Reverter
dotnet ef database update [MigracaoAnterior]
Frontend → POST /api/login
↓
Backend → Valida CPF/Senha
↓
→ Busca Aluno/Professor/Admin
↓
→ Verifica BCrypt hash
↓
→ Se válido: Gera JWT
↓
→ Retorna: id, nome, tipo, token, cursosIds, turmaId
↓
Frontend → Armazena em localStorage
↓
→ Adiciona Authorization header
↓
→ Redireciona para /aluno ou /professor ou /admin
Frontend → GET /api/nota/desempenho/{alunoId}
↓
Backend → Service.GetDesempenhoByAlunoId
↓
→ Busca todas as Notas do aluno
↓
→ Para cada nota:
- Extrai media (já calculada)
- Extrai qtdFaltas
- Calcula Nivel (BRONZE/PRATA/OURO)
↓
→ Retorna List<DesempenhoDTO>
↓
Frontend → Exibe tabela com cores por Nivel
↓
→ Renderiza gráfico com Recharts
Professor → Acessa /professor/notas
↓
→ Seleciona Materia e Turma
↓
Frontend → GET /api/nota/turma/{id}/materia/{id}
↓
Backend → Retorna lista de alunos
↓
Frontend → Renderiza formulário com inputs de nota
↓
Professor → Preenche Nota1, Nota2 para cada aluno
↓
→ POST /api/nota (List<NotaDTORequest>)
↓
Backend → Para cada nota:
- Calcula Media = (N1 + N2) / 2
- Obtém QtdFaltas
- Calcula Status (APROVADO/REPROVADO)
- Cria registro UNIQUE(AlunoId, MateriaId)
↓
→ Retorna sucesso
↓
Frontend → Toast: "Notas lançadas com sucesso!"
Professor → Acessa /professor/chamada
↓
→ Seleciona Materia e Turma
↓
Frontend → GET /api/aluno/turma/{turmaId}
↓
Backend → Lista alunos da turma
↓
Frontend → Lista com checkboxes (Presente/Faltante)
↓
Professor → Marca presença/falta
↓
→ POST /api/chamada/realizar
ou PUT /api/chamada/atualizar
↓
Backend → Verifica se já existe chamada hoje
↓
Se NÃO existe: Cria
Se SIM e é atualizar: Atualiza
Se SIM e é realizar: Exception
↓
Frontend → Toast: "Chamada registrada!"
Token contém:
Validação:
BCrypt + Salt:
Geração de Senha Aleatória:
Desenvolvimento: AllowAnyOrigin() Produção: Especificar domínios
Input Validation:
Prevenção SQL Injection:
Requisitos:
Passos:
cd backend/tivitApi
dotnet restore
dotnet ef database update
dotnet run
Configuração (appsettings.json):
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=TivitAcademy;Trusted_Connection=true;"
},
"Jwt": {
"Key": "sua-chave-secreta-minimo-32-caracteres",
"Issuer": "tivit-academy",
"Audience": "tivit-academy-users",
"ExpiresInHours": 8
},
"AWS": {
"Region": "us-east-1",
"SQSQueueUrl": "https://sqs.us-east-1.amazonaws.com/.../queue-name"
}
}
Requisitos:
Passos:
cd frontend
npm install
cp .env.example .env
# Editar VITE_API_URL=http://localhost:5027/api
npm run dev
Build para Produção:
npm run build
npm run preview
Backend Dockerfile:
FROM mcr.microsoft.com/dotnet/sdk:9.0 as build
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build /app/out .
EXPOSE 5027
ENTRYPOINT ["dotnet", "tivitApi.dll"]
| Problema | Solução |
|---|---|
| Bearer token invalid | Token expirou ou chave JWT incorreta |
| CORS error | Frontend URL não está em CORS permitidas |
| Database connection | SQL Server não está rodando ou connection string errada |
| 401 Unauthorized | Token inválido ou expirado |
| Migration failed | Reverter: dotnet ef database update <anterior> |
| Senha não funciona | Verificar hash BCrypt; Verifica senha correta |
| SQS error | Verificar credenciais AWS e URL da fila |
Backend:
Frontend:
Documentação Gerada em: 18 de Março de 2026 Versão do Projeto: 1.0.0 Status: Projeto em Desenvolvimento Ativo Autor: Documentação Técnica Automática