# PROMPT COMPLETO — Portal do Aluno (EduManager Student Portal)

> **Copie este prompt inteiro e cole em uma nova conversa para criar o projeto do zero.**

---

## Objetivo
Atue como um Desenvolvedor Sênior Full-Stack. Crie um projeto NOVO e SEPARADO chamado **"Portal do Aluno"** — uma aplicação web onde os alunos matriculados no sistema **EduManager** podem fazer login e visualizar seus dados acadêmicos e financeiros.

Este portal **NÃO faz parte do código do EduManager**. É um projeto independente que **CONSOME os mesmos dados** do EduManager, lendo diretamente do mesmo banco de dados **Supabase**.

---

## Stack Tecnológica Obrigatória
- **Frontend:** React + TypeScript + Vite
- **Backend:** Node.js + Express (server.js)
- **Banco de Dados:** Supabase (PostgreSQL) — **o mesmo banco do EduManager, apenas leitura**
- **Estilização:** TailwindCSS
- **Deploy:** Docker (Dockerfile multi-stage) para rodar no **Portainer via Docker Swarm**
- **Porta:** 3001 (para não conflitar com o EduManager que roda na 3000)

---

## Arquitetura do Banco de Dados (Supabase — SOMENTE LEITURA)

O EduManager armazena TODOS os dados da escola em uma **única tabela** chamada `school_data` com uma **única linha** (id = 1). O campo `data` é um JSON gigante com a seguinte estrutura:

```typescript
// Tabela: school_data (id: 1, coluna "data" tipo JSONB)
{
  students: Student[],       // Lista de todos os alunos
  classes: Class[],          // Lista de turmas
  courses: Course[],         // Lista de cursos
  payments: Payment[],       // Lista de todos os pagamentos/cobranças
  contracts: Contract[],     // Contratos dos alunos
  certificates: Certificate[], // Certificados emitidos
  attendance: Attendance[],  // Registros de presença
  subjects: Subject[],       // Disciplinas
  grades: Grade[],           // Notas dos alunos
  exams: Exam[],             // Avaliações (Provas e Atividades)
  profile: SchoolProfile,    // Dados da escola (nome, logo, etc.)
  logo?: string,             // Logo da escola em base64
}
```

### Interface Student (campos relevantes para login):
```typescript
interface Student {
  id: string;                    // UUID
  name: string;                  // Nome completo
  email: string;
  phone: string;
  birthDate: string;             // YYYY-MM-DD
  cpf: string;                   // Formato: 000.000.000-00
  rg?: string;
  classId: string;               // ID da turma vinculada
  status: 'active' | 'inactive' | 'cancelled';
  registrationDate: string;
  photo?: string;                // Base64 da foto do aluno
  addressZip?: string;
  addressStreet?: string;
  addressNumber?: string;
  addressNeighborhood?: string;
  addressCity?: string;
  addressState?: string;
  enrollmentNumber?: string;     // ← LOGIN (formato: MAT-202600001)
  portalPassword?: string;       // ← SENHA (padrão: 6 primeiros dígitos do CPF)
  discount?: number;
}
```

### Interface Payment (cobranças do aluno):
```typescript
interface Payment {
  id: string;
  studentId: string;             // Relaciona com Student.id
  amount: number;
  discount?: number;
  dueDate: string;               // YYYY-MM-DD
  status: 'pending' | 'paid' | 'overdue';
  paidDate?: string;
  type: 'monthly' | 'registration' | 'other';
  installmentNumber?: number;
  totalInstallments?: number;
  description?: string;
  asaasPaymentId?: string;       // ID no Asaas
  asaasPaymentUrl?: string;      // URL do boleto no Asaas
}
```

### Outras Tabelas Auxiliares no Supabase:

**Tabela `alunos_cobrancas`** (cobranças sincronizadas com Asaas):
```sql
-- Colunas principais:
id (uuid), aluno_id (uuid), asaas_customer_id (text), asaas_payment_id (text),
asaas_installment_id (text), valor (numeric), vencimento (date),
link_boleto (text), link_carne (text), status (text), created_at (timestamptz)
```

### Interface Grade (notas):
```typescript
interface Grade {
  id: string;
  studentId: string;
  subjectId: string;
  value: number;
  period: string;    // Ex: "1º Bimestre"
  examId?: string;   // ID da avaliação vinculada (se houver)
}
```

### Interface Exam (avaliações):
```typescript
interface Exam {
  id: string;
  title: string;
  evaluationType: 'exam' | 'activity';
  maxScore: number;
  subjectId?: string;
  periodId?: string;
}
```

### Interface Attendance (frequência):
```typescript
interface Attendance {
  id: string;
  studentId: string;
  classId: string;
  date: string;      // ISO String
  verified: boolean;
  type?: 'presence' | 'absence';
  justification?: string;
}
```

### Interface Class e Course:
```typescript
interface Class {
  id: string;
  name: string;
  courseId: string;
  teacher: string;
  schedule: string;
}

interface Course {
  id: string;
  name: string;
  duration: string;
  monthlyFee: number;
}
```

### Interface Contract:
```typescript
interface Contract {
  id: string;
  studentId: string;
  title: string;
  content: string;     // HTML do contrato
  createdAt: string;
}
```

### Interface Certificate:
```typescript
interface Certificate {
  id: string;
  studentId: string;
  description?: string;
  issueDate: string;
}
```

### Interface SchoolProfile:
```typescript
interface SchoolProfile {
  id: string;
  name: string;
  address: string;
  city: string;
  state: string;
  cnpj: string;
  phone: string;
  email: string;
}
```

---

## Sistema de Autenticação

### Login:
- **Usuário:** Campo `enrollmentNumber` do aluno (ex: `MAT-202600001`)
- **Senha:** Campo `portalPassword` do aluno (padrão: 6 primeiros dígitos do CPF)

### Fluxo de Login no Backend:
1. Receber `enrollmentNumber` e `password` via POST `/api/portal/login`
2. Consultar a tabela `school_data` (id=1), pegar o JSON `data`
3. Buscar no array `data.students` o aluno cujo `enrollmentNumber` = input do usuário
4. Verificar se `portalPassword` === senha digitada
5. Se válido: gerar um JWT (jsonwebtoken) com `{ studentId, enrollmentNumber, name }` e retornar
6. Se inválido: retornar 401

### Middleware de Autenticação:
- Criar middleware `authMiddleware` que valida o JWT em todas as rotas `/api/portal/*`
- O JWT secret deve vir de `process.env.JWT_SECRET`

---

## Funcionalidades do Portal (Páginas)

### 1. Tela de Login
- Design moderno, escuro, com gradientes
- Logo da escola carregada dinamicamente do Supabase (campo `data.logo`)
- Campos: Nº de Matrícula + Senha
- Botão "Entrar"
- Mensagem de erro amigável se credenciais inválidas

### 2. Dashboard (Página Inicial pós-login)
- Saudação: "Olá, {nome do aluno}!"
- Foto do aluno (se tiver)
- Cards resumo:
  - **Turma:** nome da turma e curso vinculado
  - **Financeiro:** total de parcelas pendentes / valor total em aberto
  - **Frequência:** porcentagem de presença
  - **Próximo vencimento:** data e valor

### 3. Financeiro (Meus Boletos)
- Tabela listando TODOS os pagamentos do aluno (filtrados por `studentId`)
- Colunas: Descrição, Vencimento, Valor, Status (badges coloridos), Ação
- Botão "Ver Boleto" que abre o link do Asaas (`asaasPaymentUrl` ou buscar da tabela `alunos_cobrancas.link_boleto`)
- Filtros: Todos, Pendentes, Pagos, Atrasados
- Destaque visual para boletos atrasados (vermelho)

### 4. Notas / Boletim
- Buscar no array `data.grades` todas as notas onde `studentId` = aluno logado
- Buscar os nomes das disciplinas no array `data.subjects`
- Exibir em formato de tabela/boletim organizada por período (1º Bimestre, 2º Bimestre, etc.)
- Calcular média automaticamente

### 5. Frequência / Presença
- Buscar no array `data.attendance` onde `studentId` = aluno logado
- Mostrar calendário ou lista com os dias de presença/falta
- Exibir porcentagem total de frequência
- Justificativas de falta quando houver

### 6. Contratos
- Listar contratos do aluno (array `data.contracts` filtrado por `studentId`)
- Botão para visualizar o contrato completo (renderizar HTML)
- Botão para download/impressão

### 7. Certificados
- Listar certificados emitidos para o aluno
- Botão para visualizar/download

### 8. Meus Dados
- Exibir dados pessoais do aluno (somente leitura):
  - Nome, CPF, RG, Data de Nascimento, Telefone, Email
  - Endereço completo
  - Dados do responsável (se tiver)
- Botão "Alterar Senha" que permite trocar a `portalPassword`
  - Para salvar a nova senha: fazer PUT no server.js que atualiza o campo `portalPassword` do aluno no JSON `data.students` dentro da `school_data`

---

## Rotas do Backend (server.js)

```
POST   /api/portal/login             → Autenticação (retorna JWT)
GET    /api/portal/me                → Dados do aluno logado (protegido)
GET    /api/portal/financeiro        → Pagamentos do aluno (protegido)
GET    /api/portal/notas             → Notas/boletim do aluno (protegido)
GET    /api/portal/frequencia        → Registros de presença (protegido)
GET    /api/portal/contratos         → Contratos do aluno (protegido)
GET    /api/portal/certificados      → Certificados do aluno (protegido)
GET    /api/portal/boletos           → Boletos do Asaas (tabela alunos_cobrancas) (protegido)
PUT    /api/portal/alterar-senha     → Alterar senha do portal (protegido)
GET    /api/portal/escola            → Dados da escola + logo (público, para o login)
```

---

## Variáveis de Ambiente (Portainer)

```env
PORT=3001
VITE_SUPABASE_URL=https://xxxx.supabase.co
VITE_SUPABASE_KEY=eyJhb...
JWT_SECRET=uma-chave-secreta-forte-aqui
```

---

## Dockerfile (Multi-stage, igual ao EduManager)

```dockerfile
# ---- Build Stage ----
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# ---- Production Stage ----
FROM node:22-alpine AS production
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY server.js ./
COPY --from=builder /app/dist ./dist
EXPOSE 3001
CMD ["node", "server.js"]
```

---

## Regras e Restrições CRÍTICAS

1. **SOMENTE LEITURA** no Supabase — o portal NÃO deve criar, editar ou excluir alunos, pagamentos, notas, etc. A ÚNICA exceção é a rota `PUT /api/portal/alterar-senha` que atualiza o campo `portalPassword` dentro do JSON.

2. **Nunca expor dados de outros alunos** — todas as queries devem filtrar por `studentId` do JWT.

3. **Design Premium** — Use dark mode por padrão, gradientes modernos, animações suaves, tipografia Google Fonts (Inter ou Outfit). O visual deve ser profissional e bonito.

4. **Responsivo** — Deve funcionar perfeitamente em celulares (a maioria dos alunos acessará pelo celular).

5. **O projeto deve ser 100% funcional** — sem mocks, sem placeholder. Lê dados reais do Supabase.

6. **Separação total do EduManager** — Este é um projeto em pasta separada, repositório separado, container Docker separado. Eles compartilham apenas o banco Supabase.

---

## Estrutura de Pastas Esperada

```
portal-aluno/
├── server.js              # Backend Express
├── Dockerfile
├── package.json
├── vite.config.ts
├── tsconfig.json
├── index.html
├── src/
│   ├── main.tsx
│   ├── App.tsx
│   ├── types.ts           # Interfaces compartilhadas
│   ├── context/
│   │   └── AuthContext.tsx # Context de autenticação (JWT)
│   ├── pages/
│   │   ├── Login.tsx
│   │   ├── Dashboard.tsx
│   │   ├── Financeiro.tsx
│   │   ├── Notas.tsx
│   │   ├── Frequencia.tsx
│   │   ├── Contratos.tsx
│   │   ├── Certificados.tsx
│   │   └── MeusDados.tsx
│   ├── components/
│   │   ├── Sidebar.tsx
│   │   ├── Header.tsx
│   │   └── ProtectedRoute.tsx
│   └── styles/
│       └── index.css
```

---

**Gere o projeto completo com TODOS os arquivos acima, funcional e pronto para deploy no Docker/Portainer.**
