# 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` → `` ### 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