From 8fbb54c977fbedf2630b4a9920c4c4c6e55ec0a7 Mon Sep 17 00:00:00 2001
From: Tiago Yamamoto
Date: Tue, 17 Feb 2026 09:42:31 -0300
Subject: [PATCH] refactor job posting routes and add dashboard job creation
page
---
docs/TASKS.md | 2 +-
docs/publicar-vaga-routes.md | 11 +-
frontend/FRONTEND.md | 4 +-
frontend/src/app/about/page.tsx | 2 +-
frontend/src/app/contact/page.tsx | 2 +-
frontend/src/app/dashboard/jobs/new/page.tsx | 294 ++++++++++++++-
frontend/src/app/dashboard/jobs/page.tsx | 2 +-
frontend/src/app/dashboard/my-jobs/page.tsx | 4 +-
.../app/{post-job => jobs/new}/page.test.tsx | 0
.../src/app/{post-job => jobs/new}/page.tsx | 0
.../{post-job => jobs/new}/translations.ts | 0
frontend/src/app/publicar-vaga/page.tsx | 349 +-----------------
frontend/src/components/company-sidebar.tsx | 2 +-
frontend/src/components/footer.tsx | 2 +-
14 files changed, 310 insertions(+), 364 deletions(-)
rename frontend/src/app/{post-job => jobs/new}/page.test.tsx (100%)
rename frontend/src/app/{post-job => jobs/new}/page.tsx (100%)
rename frontend/src/app/{post-job => jobs/new}/translations.ts (100%)
diff --git a/docs/TASKS.md b/docs/TASKS.md
index 6b97bc9..e52e171 100644
--- a/docs/TASKS.md
+++ b/docs/TASKS.md
@@ -24,7 +24,7 @@ Lista detalhada de tarefas para evitar retrabalho.
- Frontend: profileApi.uploadAvatar
- [x] **Public Job Posting**
- - Frontend: `/post-job` page
+ - Frontend: `/jobs/new` page
- 3-step wizard (Company + Job + Confirm)
- [x] **Documentation**
diff --git a/docs/publicar-vaga-routes.md b/docs/publicar-vaga-routes.md
index 67adb68..f73f32f 100644
--- a/docs/publicar-vaga-routes.md
+++ b/docs/publicar-vaga-routes.md
@@ -2,11 +2,12 @@
As principais rotas usadas para publicar vagas no projeto são:
-1. `/publicar-vaga` — landing/formulário público de anúncio de vaga.
-2. `/post-job` — fluxo principal multi-etapas para publicação com dados da empresa e da vaga.
-3. `/register/job` — formulário público alternativo para criação de vaga.
+1. `/jobs/new` — fluxo público principal (multi-etapas) para publicação com dados da empresa e da vaga.
+2. `/publicar-vaga` — rota legada redirecionando para `/jobs/new`.
+3. `/dashboard/jobs/new` — fluxo interno no dashboard para cadastro rápido de vaga (design system do dashboard).
+4. `/register/job` — formulário público alternativo para criação de vaga.
## Pontos de entrada no sistema
-- Link para `/publicar-vaga` na página **About** e no **Footer**.
-- Link para `/post-job` na página **Contact**.
+- Link para `/jobs/new` na página **About**, **Footer** e **Contact**.
+- Link para `/dashboard/jobs/new` nas páginas internas do dashboard (Jobs, My Jobs e sidebar da empresa).
diff --git a/frontend/FRONTEND.md b/frontend/FRONTEND.md
index 4af7b1f..2af81b4 100644
--- a/frontend/FRONTEND.md
+++ b/frontend/FRONTEND.md
@@ -72,7 +72,7 @@ src/
│ ├── page.tsx # Landing page
│ ├── login/ # Autenticação
│ ├── register/ # Registro (candidate, company)
-│ ├── post-job/ # **NEW** Wizard público
+│ ├── jobs/new/ # **NEW** Wizard público
│ ├── jobs/ # Listagem e detalhes
│ │ ├── page.tsx # Listagem
│ │ ├── [id]/page.tsx # Detalhes
@@ -143,7 +143,7 @@ src/
| `/login` | Login |
| `/register/candidate` | Registro candidato |
| `/register/company` | Registro empresa |
-| `/post-job` | **NEW** Wizard público (registro + vaga) |
+| `/jobs/new` | **NEW** Wizard público (registro + vaga) |
| `/about` | Sobre |
| `/contact` | Contato |
| `/faq` | FAQ |
diff --git a/frontend/src/app/about/page.tsx b/frontend/src/app/about/page.tsx
index f43761a..7b0f157 100644
--- a/frontend/src/app/about/page.tsx
+++ b/frontend/src/app/about/page.tsx
@@ -243,7 +243,7 @@ export default function AboutPage() {
{t('about.cta.findJobs')}
{t('about.cta.postJob')}
diff --git a/frontend/src/app/contact/page.tsx b/frontend/src/app/contact/page.tsx
index 648388b..2925f20 100644
--- a/frontend/src/app/contact/page.tsx
+++ b/frontend/src/app/contact/page.tsx
@@ -152,7 +152,7 @@ export default function ContactPage() {
-
+
diff --git a/frontend/src/app/dashboard/jobs/new/page.tsx b/frontend/src/app/dashboard/jobs/new/page.tsx
index 642716a..1b15f29 100644
--- a/frontend/src/app/dashboard/jobs/new/page.tsx
+++ b/frontend/src/app/dashboard/jobs/new/page.tsx
@@ -1,5 +1,293 @@
-import { redirect } from "next/navigation"
+"use client"
-export default function DashboardNewJobRedirectPage() {
- redirect("/publicar-vaga")
+import { useEffect, useState } from "react"
+import { Loader2, PlusCircle } from "lucide-react"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+import { Textarea } from "@/components/ui/textarea"
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
+import { adminCompaniesApi, jobsApi, type AdminCompany, type CreateJobPayload } from "@/lib/api"
+
+export default function DashboardNewJobPage() {
+ const [loading, setLoading] = useState(false)
+ const [loadingCompanies, setLoadingCompanies] = useState(true)
+ const [companies, setCompanies] = useState([])
+
+ const [formData, setFormData] = useState({
+ title: "",
+ description: "",
+ location: "",
+ salaryMin: "",
+ salaryMax: "",
+ salaryType: "monthly",
+ currency: "BRL",
+ employmentType: "",
+ workingHours: "",
+ companyId: "",
+ })
+
+ useEffect(() => {
+ const loadCompanies = async () => {
+ try {
+ setLoadingCompanies(true)
+ const data = await adminCompaniesApi.list(undefined, 1, 100)
+ setCompanies(data.data ?? [])
+ } catch (error) {
+ console.error("Falha ao carregar empresas:", error)
+ toast.error("Falha ao carregar empresas")
+ } finally {
+ setLoadingCompanies(false)
+ }
+ }
+
+ loadCompanies()
+ }, [])
+
+ const canSubmit =
+ formData.title.trim().length >= 5 &&
+ formData.description.trim().length >= 20 &&
+ formData.companyId !== ""
+
+ const handleInputChange = (field: string, value: string) => {
+ setFormData((prev) => ({ ...prev, [field]: value }))
+ }
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault()
+
+ if (!canSubmit) {
+ toast.error("Preencha os campos obrigatórios")
+ return
+ }
+
+ setLoading(true)
+ try {
+ const payload: CreateJobPayload = {
+ companyId: formData.companyId,
+ title: formData.title,
+ description: formData.description,
+ location: formData.location || undefined,
+ employmentType:
+ (formData.employmentType as CreateJobPayload["employmentType"]) || undefined,
+ salaryMin: formData.salaryMin ? parseFloat(formData.salaryMin) : undefined,
+ salaryMax: formData.salaryMax ? parseFloat(formData.salaryMax) : undefined,
+ salaryType: (formData.salaryType as CreateJobPayload["salaryType"]) || undefined,
+ currency: (formData.currency as CreateJobPayload["currency"]) || undefined,
+ workingHours: formData.workingHours || undefined,
+ status: "draft",
+ }
+
+ await jobsApi.create(payload)
+ toast.success("Vaga cadastrada no dashboard com sucesso")
+ setFormData({
+ title: "",
+ description: "",
+ location: "",
+ salaryMin: "",
+ salaryMax: "",
+ salaryType: "monthly",
+ currency: "BRL",
+ employmentType: "",
+ workingHours: "",
+ companyId: "",
+ })
+ } catch (error: any) {
+ console.error("Falha ao cadastrar vaga:", error)
+ toast.error(error.message || "Falha ao cadastrar vaga")
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ return (
+
+
+
+
Nova vaga
+
+ Cadastre vagas usando o padrão visual do dashboard.
+
+
+
+
+
+
+
+ Dados da vaga
+
+
+ Informe os detalhes obrigatórios para criar a vaga em rascunho.
+
+
+
+
+
+
+
+ )
}
diff --git a/frontend/src/app/dashboard/jobs/page.tsx b/frontend/src/app/dashboard/jobs/page.tsx
index 10449d1..74fffd1 100644
--- a/frontend/src/app/dashboard/jobs/page.tsx
+++ b/frontend/src/app/dashboard/jobs/page.tsx
@@ -191,7 +191,7 @@ export default function AdminJobsPage() {
{t('admin.jobs.title')}
{t('admin.jobs.subtitle')}
-
+
-
+