feat(jobs/new): add user account registration and fix companyId in job payload
- Add password + confirm-password fields to billing step (Step 3) so the recruiter creates their account credentials during the job posting flow - Validate password length (≥8) and confirmation match before proceeding - Extract company `id` from POST /auth/register/company response and send it as `companyId` in the job creation payload (was missing — caused 400) - Pass `contact` (full name) to company registration endpoint - Remove hardcoded "Temp@123456" password; use the user-provided one - Remove hardcoded "+55" phone prefix; send raw digits with "+" prefix - Add translations (pt-BR, en, es) for password fields and error messages Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
61d64d846a
commit
2686b69506
1 changed files with 67 additions and 4 deletions
|
|
@ -179,6 +179,12 @@ const contentByLocale = {
|
|||
phonePlaceholder: "(00) 0000-0000",
|
||||
mobile: "Celular",
|
||||
mobilePlaceholder: "(00) 00000-0000",
|
||||
accountTitle: "Dados de acesso à conta",
|
||||
accountHint: "Você usará este e-mail e senha para acessar o painel da empresa.",
|
||||
password: "Senha *",
|
||||
passwordPlaceholder: "Mínimo 8 caracteres",
|
||||
confirmPassword: "Confirmar senha *",
|
||||
confirmPasswordPlaceholder: "Repita a senha",
|
||||
termsAccept: "Li e aceito as",
|
||||
termsLink: "Condições Legais",
|
||||
termsAnd: "e a",
|
||||
|
|
@ -218,6 +224,8 @@ const contentByLocale = {
|
|||
paymentRequired: "Selecione um método de pagamento.",
|
||||
registerError: "Erro ao registrar empresa",
|
||||
unexpectedError: "Erro inesperado ao publicar vaga",
|
||||
passwordRequired: "Informe uma senha com ao menos 8 caracteres.",
|
||||
passwordMismatch: "As senhas não coincidem.",
|
||||
},
|
||||
success: "Vaga cadastrada com sucesso!",
|
||||
},
|
||||
|
|
@ -335,6 +343,12 @@ const contentByLocale = {
|
|||
phonePlaceholder: "(00) 0000-0000",
|
||||
mobile: "Mobile",
|
||||
mobilePlaceholder: "(00) 00000-0000",
|
||||
accountTitle: "Account access details",
|
||||
accountHint: "You will use this email and password to access the company dashboard.",
|
||||
password: "Password *",
|
||||
passwordPlaceholder: "Minimum 8 characters",
|
||||
confirmPassword: "Confirm password *",
|
||||
confirmPasswordPlaceholder: "Repeat password",
|
||||
termsAccept: "I have read and accept the",
|
||||
termsLink: "Legal Terms",
|
||||
termsAnd: "and the",
|
||||
|
|
@ -374,6 +388,8 @@ const contentByLocale = {
|
|||
paymentRequired: "Please select a payment method.",
|
||||
registerError: "Error registering company",
|
||||
unexpectedError: "Unexpected error publishing job",
|
||||
passwordRequired: "Please enter a password with at least 8 characters.",
|
||||
passwordMismatch: "Passwords do not match.",
|
||||
},
|
||||
success: "Job posted successfully!",
|
||||
},
|
||||
|
|
@ -491,6 +507,12 @@ const contentByLocale = {
|
|||
phonePlaceholder: "(00) 0000-0000",
|
||||
mobile: "Celular",
|
||||
mobilePlaceholder: "(00) 00000-0000",
|
||||
accountTitle: "Datos de acceso a la cuenta",
|
||||
accountHint: "Usará este correo y contraseña para acceder al panel de la empresa.",
|
||||
password: "Contraseña *",
|
||||
passwordPlaceholder: "Mínimo 8 caracteres",
|
||||
confirmPassword: "Confirmar contraseña *",
|
||||
confirmPasswordPlaceholder: "Repita la contraseña",
|
||||
termsAccept: "He leído y acepto las",
|
||||
termsLink: "Condiciones Legales",
|
||||
termsAnd: "y la",
|
||||
|
|
@ -530,6 +552,8 @@ const contentByLocale = {
|
|||
paymentRequired: "Seleccione un método de pago.",
|
||||
registerError: "Error al registrar empresa",
|
||||
unexpectedError: "Error inesperado al publicar vacante",
|
||||
passwordRequired: "Ingrese una contraseña con al menos 8 caracteres.",
|
||||
passwordMismatch: "Las contraseñas no coinciden.",
|
||||
},
|
||||
success: "¡Vacante publicada con éxito!",
|
||||
},
|
||||
|
|
@ -593,6 +617,8 @@ export default function PostJobPage() {
|
|||
contactEmail: "",
|
||||
contactPhone: "",
|
||||
contactMobile: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
acceptTerms: false,
|
||||
acceptMarketing: false,
|
||||
});
|
||||
|
|
@ -655,6 +681,14 @@ export default function PostJobPage() {
|
|||
toast.error(c.errors.billingEmailInvalid);
|
||||
return false;
|
||||
}
|
||||
if (!billing.password || billing.password.length < 8) {
|
||||
toast.error(c.errors.passwordRequired);
|
||||
return false;
|
||||
}
|
||||
if (billing.password !== billing.confirmPassword) {
|
||||
toast.error(c.errors.passwordMismatch);
|
||||
return false;
|
||||
}
|
||||
if (!billing.acceptTerms) {
|
||||
toast.error(c.errors.termsRequired);
|
||||
return false;
|
||||
|
|
@ -688,8 +722,8 @@ export default function PostJobPage() {
|
|||
setLoading(true);
|
||||
try {
|
||||
const apiBase = process.env.NEXT_PUBLIC_API_URL || "";
|
||||
const password = "Temp@123456";
|
||||
const billingPhone = cleanDigits(billing.contactMobile || billing.contactPhone || job.applicationPhone);
|
||||
const contactFullName = [billing.contactName, billing.contactLastName].filter(Boolean).join(" ");
|
||||
|
||||
const registerRes = await fetch(`${apiBase}/api/v1/auth/register/company`, {
|
||||
method: "POST",
|
||||
|
|
@ -697,9 +731,10 @@ export default function PostJobPage() {
|
|||
body: JSON.stringify({
|
||||
companyName: company.name,
|
||||
email: billing.contactEmail,
|
||||
contact: contactFullName || null,
|
||||
document: cleanDigits(company.document) || null,
|
||||
password,
|
||||
phone: billingPhone ? `+55${billingPhone}` : null,
|
||||
password: billing.password,
|
||||
phone: billingPhone ? `+${billingPhone}` : null,
|
||||
website: company.website || null,
|
||||
employeeCount: company.employeeCount || null,
|
||||
foundedYear: company.foundedYear ? Number(company.foundedYear) : null,
|
||||
|
|
@ -712,7 +747,7 @@ export default function PostJobPage() {
|
|||
throw new Error(err.message || c.errors.registerError);
|
||||
}
|
||||
|
||||
const { token } = await registerRes.json();
|
||||
const { id: companyId, token } = await registerRes.json();
|
||||
|
||||
const salaryMin = job.salaryMode === "fixed" ? Number(job.salaryFixed || 0) : Number(job.salaryMin || 0);
|
||||
const salaryMax = job.salaryMode === "fixed" ? Number(job.salaryFixed || 0) : Number(job.salaryMax || 0);
|
||||
|
|
@ -724,6 +759,7 @@ export default function PostJobPage() {
|
|||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
companyId,
|
||||
title: job.title,
|
||||
description: job.description,
|
||||
location: `${job.location}, ${job.country}`,
|
||||
|
|
@ -1227,6 +1263,33 @@ export default function PostJobPage() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border rounded-lg p-4 space-y-4 bg-gray-50">
|
||||
<div>
|
||||
<h4 className="font-semibold text-[#1d2c44]">{c.billing.accountTitle}</h4>
|
||||
<p className="text-xs text-muted-foreground mt-1">{c.billing.accountHint}</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<Label>{c.billing.password}</Label>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder={c.billing.passwordPlaceholder}
|
||||
value={billing.password}
|
||||
onChange={(e) => setBilling({ ...billing, password: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>{c.billing.confirmPassword}</Label>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder={c.billing.confirmPasswordPlaceholder}
|
||||
value={billing.confirmPassword}
|
||||
onChange={(e) => setBilling({ ...billing, confirmPassword: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{c.billing.billingAddress}</Label>
|
||||
<textarea
|
||||
|
|
|
|||
Loading…
Reference in a new issue