Files
mercado.clube67.com/docs/bancoTalentos.md
T

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