241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
# Banco de Talentos — Plano de Implementação
|
|
|
|
## Visão geral
|
|
Sistema completo de vagas de emprego integrado à plataforma multi-tenant:
|
|
- **Landing page pública** — vitrine de vagas por empresa com data e contagem de candidatos
|
|
- **Área do candidato** — cadastro de currículo e candidatura a vagas
|
|
- **Painel admin** — gestão completa de vagas, candidatos e currículos
|
|
|
|
---
|
|
|
|
## 1. Banco de Dados — sistema-nuvem
|
|
|
|
### 1.1 Tabela `jobs` (vagas)
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS jobs (
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INT NOT NULL,
|
|
title TEXT NOT NULL,
|
|
description TEXT NOT NULL,
|
|
requirements TEXT,
|
|
benefits TEXT,
|
|
location TEXT,
|
|
work_mode TEXT NOT NULL DEFAULT 'presencial', -- presencial | híbrido | remoto
|
|
job_type TEXT NOT NULL DEFAULT 'clt', -- clt | pj | freelance | estagio | temporario
|
|
category TEXT,
|
|
salary_min NUMERIC(10,2),
|
|
salary_max NUMERIC(10,2),
|
|
salary_hide BOOLEAN NOT NULL DEFAULT false,
|
|
slots INT NOT NULL DEFAULT 1,
|
|
active BOOLEAN NOT NULL DEFAULT true,
|
|
published_at TIMESTAMPTZ DEFAULT NOW(),
|
|
expires_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
### 1.2 Tabela `resumes` (currículos)
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS resumes (
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INT NOT NULL,
|
|
user_cpf TEXT NOT NULL,
|
|
user_nome TEXT NOT NULL,
|
|
email TEXT,
|
|
phone TEXT,
|
|
linkedin TEXT,
|
|
portfolio TEXT,
|
|
about TEXT,
|
|
experience JSONB NOT NULL DEFAULT '[]',
|
|
-- [{ company, role, start, end, current, description }]
|
|
education JSONB NOT NULL DEFAULT '[]',
|
|
-- [{ institution, degree, course, start, end, current }]
|
|
skills JSONB NOT NULL DEFAULT '[]',
|
|
-- [{ name, level }] level: basico | intermediario | avancado
|
|
file_url TEXT, -- PDF anexado pelo candidato
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE (tenant_id, user_cpf)
|
|
);
|
|
```
|
|
|
|
### 1.3 Tabela `job_applications` (candidaturas)
|
|
```sql
|
|
CREATE TABLE IF NOT EXISTS job_applications (
|
|
id SERIAL PRIMARY KEY,
|
|
tenant_id INT NOT NULL,
|
|
job_id INT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
|
|
resume_id INT REFERENCES resumes(id),
|
|
applicant_nome TEXT NOT NULL,
|
|
applicant_email TEXT,
|
|
applicant_phone TEXT,
|
|
applicant_cpf TEXT NOT NULL,
|
|
cover_letter TEXT,
|
|
status TEXT NOT NULL DEFAULT 'novo',
|
|
-- novo | em_analise | aprovado | reprovado | contratado
|
|
admin_notes TEXT,
|
|
applied_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
UNIQUE (job_id, applicant_cpf)
|
|
);
|
|
```
|
|
|
|
### 1.4 Índices
|
|
```sql
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_tenant ON jobs(tenant_id, active);
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_published ON jobs(published_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_applications_job ON job_applications(job_id);
|
|
CREATE INDEX IF NOT EXISTS idx_resumes_cpf ON resumes(tenant_id, user_cpf);
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Backend — sistema-nuvem/controllers + routes
|
|
|
|
### 2.1 Endpoints públicos (customer-app)
|
|
- [x] `GET /api/jobs` — listar vagas ativas com contagem de candidatos
|
|
- Query params: `category`, `work_mode`, `job_type`, `limit`, `offset`
|
|
- Retorna: `{ jobs, total }` — cada vaga inclui `applicants_count`
|
|
- [x] `GET /api/jobs/:id` — detalhe da vaga (sem candidatos)
|
|
- [x] `POST /api/jobs/:id/apply` — candidatar-se a uma vaga
|
|
- Body: `{ applicant_cpf, applicant_nome, applicant_phone, applicant_email, cover_letter, resume_id? }`
|
|
- Impede candidatura duplicada (mesmo CPF + vaga)
|
|
|
|
### 2.2 Endpoints do candidato (autenticado — `verifyUserToken`)
|
|
- [x] `GET /api/user/resume` — buscar currículo do usuário logado
|
|
- [x] `POST /api/user/resume` — criar currículo
|
|
- [x] `PUT /api/user/resume` — atualizar currículo completo
|
|
- [ ] `POST /api/user/resume/upload` — upload de PDF (multer → `/public/resumes/`)
|
|
- [x] `GET /api/user/applications` — listar candidaturas do usuário
|
|
- [x] `DELETE /api/user/applications/:id` — cancelar candidatura (se ainda `novo`)
|
|
|
|
### 2.3 Endpoints admin (autenticado — `verifyToken`)
|
|
- [x] `GET /api/admin/jobs` — listar todas as vagas com `applicants_count`
|
|
- Query: `active`, `category`, `work_mode`, `search`, `limit`, `offset`
|
|
- [x] `POST /api/admin/jobs` — criar vaga
|
|
- [x] `PUT /api/admin/jobs/:id` — editar vaga
|
|
- [x] `PATCH /api/admin/jobs/:id/toggle` — ativar / desativar vaga
|
|
- [x] `DELETE /api/admin/jobs/:id` — remover vaga (apenas sem candidatos, senão desativar)
|
|
- [x] `GET /api/admin/jobs/:id/applications` — candidatos de uma vaga
|
|
- Query: `status`, `limit`, `offset`
|
|
- Retorna dados + currículo vinculado
|
|
- [x] `GET /api/admin/applications/:id` — detalhe de candidatura com currículo completo
|
|
- [x] `PATCH /api/admin/applications/:id` — atualizar status + notas admin
|
|
- [x] `GET /api/admin/resumes` — buscar currículos por CPF / nome
|
|
- [x] `GET /api/admin/resumes/:cpf` — currículo completo de um candidato
|
|
|
|
---
|
|
|
|
## 3. Admin App — admin-app/src
|
|
|
|
### 3.1 Sidebar + Rota
|
|
- [x] Adicionar item **Vagas** no sidebar de `App.tsx` (ícone: `Briefcase`)
|
|
- [x] Nova rota `/jobs` → `<JobsPage />`
|
|
|
|
### 3.2 JobsService — services/api.ts
|
|
- [x] `list(params)`, `create(data)`, `update(id, data)`, `toggle(id)`, `remove(id)`
|
|
- [x] `getApplications(jobId, params)`, `getApplication(id)`, `updateApplication(id, data)`
|
|
- [x] `searchResumes(params)`, `getResume(cpf)`, `kpi()`
|
|
|
|
### 3.3 JobsPage.tsx — visão geral
|
|
- [x] **Header** com: total de vagas ativas, total de candidaturas, botão "Nova Vaga"
|
|
- [x] **KPI cards**: Vagas ativas · Vagas encerradas · Total candidatos · Contratações
|
|
- [x] **Tabela/lista de vagas** com colunas:
|
|
- Título · Categoria · Modo · Tipo · Publicado em · Expira em · Candidatos · Status · Ações
|
|
- [x] Filtros: busca por título, categoria, modo de trabalho, status (ativo/inativo)
|
|
- [x] Paginação
|
|
- [x] Botão **Ver candidatos** por vaga (abre drawer lateral)
|
|
- [x] Botões **Editar** / **Ativar-Desativar** / **Excluir** por linha
|
|
|
|
### 3.4 JobModal — criar / editar vaga
|
|
- [x] Título, Descrição, Requisitos, Benefícios, Localização
|
|
- [x] Modo de trabalho (select: Presencial / Híbrido / Remoto)
|
|
- [x] Tipo de contrato (select: CLT / PJ / Freelance / Estágio / Temporário)
|
|
- [x] Categoria, Número de vagas, Salário (min · max · checkbox "A combinar")
|
|
- [x] Data de expiração (opcional), Ativa (toggle)
|
|
|
|
### 3.5 ApplicationsDrawer — candidatos de uma vaga
|
|
- [x] Lista de candidatos com: nome, CPF, telefone, data de candidatura, status
|
|
- [x] Filtro por status
|
|
- [x] Clicar em candidato → abre `CandidateDetailModal`
|
|
|
|
### 3.6 CandidateDetailModal — perfil completo do candidato
|
|
- [x] Dados pessoais do candidato
|
|
- [x] Carta de apresentação (se enviou)
|
|
- [x] Currículo completo inline: Sobre · Experiências · Formação · Habilidades
|
|
- [x] Selector de status com cores: Novo · Em Análise · Aprovado · Reprovado · Contratado
|
|
- [x] Campo de notas internas do admin
|
|
- [x] Botão **Salvar status + notas**
|
|
- [x] Botão **Baixar currículo PDF** (se disponível)
|
|
|
|
### 3.7 ResumesView — banco de currículos
|
|
- [x] Busca por nome ou CPF
|
|
- [x] Tabela: nome, CPF, e-mail, telefone, última atualização, vagas candidatadas
|
|
- [x] Clicar → abre currículo completo
|
|
|
|
---
|
|
|
|
## 4. Customer App — customer-app/src
|
|
|
|
### 4.1 Landing page — seção Vagas
|
|
- [x] Nova seção `VagasSection` em `LandingPage.tsx`
|
|
- [x] Grid de cards de vagas (máx. 6 na landing, link "Ver todas")
|
|
- [x] Card de vaga inclui título, modo, tipo, localização, salário, data, candidatos
|
|
- [x] Link "Ver todas as vagas" → `/vagas`
|
|
- [x] Seção só aparece se houver vagas ativas
|
|
|
|
### 4.2 JobsAPI — api.ts
|
|
- [x] `list(params)`, `get(id)`, `apply(id, data)`
|
|
- [x] `myResume()`, `saveResume(data)`, `myApplications()`, `cancelApplication(id)`
|
|
|
|
### 4.3 Nova página — VagasListPage `/vagas`
|
|
- [x] Listagem completa de vagas com filtros por palavra-chave, modo e tipo
|
|
- [x] Cards modernos com todas as informações
|
|
- [x] Paginação (12 por página)
|
|
|
|
### 4.4 Nova página — VagaDetailPage `/vagas/:id`
|
|
- [x] Descrição completa + requisitos + benefícios
|
|
- [x] Info: localização, modo, tipo, salário, data, candidatos
|
|
- [x] Formulário de candidatura com auto-preenchimento se logado
|
|
- [x] Badge "Você já se candidatou" + status da candidatura se já aplicou
|
|
|
|
### 4.5 Área do Membro — DashboardPage
|
|
- [x] Nova aba **"Vagas"** no dashboard
|
|
- [x] Sub-aba **"Minhas Candidaturas"**: lista com vaga, data, status (badge colorido)
|
|
- [x] Sub-aba **"Meu Currículo"**: ResumeBuilder completo
|
|
|
|
### 4.6 Construtor de Currículo — ResumeBuilder
|
|
- [x] Seção **Dados Pessoais**: nome, e-mail, telefone, LinkedIn, portfólio, sobre
|
|
- [x] Seção **Experiências** (lista dinâmica): empresa, cargo, início, fim, atual, descrição
|
|
- [x] Seção **Formação** (lista dinâmica): instituição, grau, curso, início, fim
|
|
- [x] Seção **Habilidades** (lista dinâmica): nome + nível
|
|
- [x] Botão **Salvar Currículo**
|
|
|
|
### 4.7 Navbar — novo link
|
|
- [x] Adicionar "Vagas" na Navbar com `to="/vagas"`
|
|
|
|
---
|
|
|
|
## 5. Rotas novas — server.js
|
|
- [x] Montar controller `jobController.js` com todos os endpoints
|
|
- [x] Registrar todas as rotas em `server.js`
|
|
|
|
---
|
|
|
|
## Ordem de implementação
|
|
|
|
1. [x] Banco: criar tabelas `jobs`, `resumes`, `job_applications` + índices
|
|
2. [x] Backend: controller + rotas públicas (listar vagas, candidatar)
|
|
3. [x] Backend: rotas do candidato (currículo, candidaturas)
|
|
4. [x] Backend: rotas admin (CRUD vagas, candidatos, currículos)
|
|
5. [x] Admin: JobsService + JobsPage + JobModal
|
|
6. [x] Admin: ApplicationsDrawer + CandidateDetailModal
|
|
7. [x] Admin: ResumesView (integrada na JobsPage)
|
|
8. [x] Customer: JobsAPI + seção Vagas na landing
|
|
9. [x] Customer: VagasListPage + VagaDetailPage
|
|
10. [x] Customer: ResumeBuilder no Dashboard
|
|
11. [x] Customer: aba Vagas/Candidaturas no Dashboard
|
|
12. [x] Navbar: link Vagas
|
|
13. [x] Build dos 3 apps (customer-app + admin-app) — zero erros TS
|