"use client" import { useCallback, useEffect, useMemo, useRef, 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 { Checkbox } from "@/components/ui/checkbox" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Textarea } from "@/components/ui/textarea" import { adminCompaniesApi, jobsApi, type AdminCompany, type CreateJobPayload } from "@/lib/api" type ApplicationChannel = "email" | "url" | "phone" type LocationResult = { id: number name: string type: "city" | "state" country_id: number state_id?: number region_name?: string } type ApiCountry = { id: number name: string iso2: string } export default function DashboardNewJobPage() { const [loading, setLoading] = useState(false) const [loadingCompanies, setLoadingCompanies] = useState(true) const [companies, setCompanies] = useState([]) const [formData, setFormData] = useState({ companyId: "", title: "", description: "", location: "", country: "", employmentType: "", workMode: "", workingHours: "", salaryMin: "", salaryMax: "", salaryType: "monthly", currency: "BRL", salaryNegotiable: false, languageLevel: "", applicationChannel: "email" as ApplicationChannel, applicationEmail: "", applicationUrl: "", applicationPhone: "", resumeRequirement: "optional", visaSupport: false, status: "draft", }) // Location autocomplete state const [apiCountries, setApiCountries] = useState([]) const [locationIds, setLocationIds] = useState<{ cityId: number | null; regionId: number | null }>({ cityId: null, regionId: null }) const [locationResults, setLocationResults] = useState([]) const [locationSearching, setLocationSearching] = useState(false) const [showLocationDropdown, setShowLocationDropdown] = useState(false) const locationRef = useRef(null) // Load companies useEffect(() => { adminCompaniesApi.list(undefined, 1, 100) .then((data) => setCompanies(data.data ?? [])) .catch(() => toast.error("Falha ao carregar empresas")) .finally(() => setLoadingCompanies(false)) }, []) // Load countries for location autocomplete useEffect(() => { const apiBase = process.env.NEXT_PUBLIC_API_URL || "" fetch(`${apiBase}/api/v1/locations/countries`) .then((r) => r.json()) .then((data: ApiCountry[]) => setApiCountries(data)) .catch(() => {}) }, []) const selectedCountryId = useMemo( () => apiCountries.find((c) => c.iso2 === formData.country)?.id ?? null, [apiCountries, formData.country] ) const searchLocation = useCallback((query: string, countryId: number) => { const apiBase = process.env.NEXT_PUBLIC_API_URL || "" setLocationSearching(true) fetch(`${apiBase}/api/v1/locations/search?q=${encodeURIComponent(query)}&country_id=${countryId}`) .then((r) => r.json()) .then((data) => { setLocationResults(Array.isArray(data) ? data : []) setShowLocationDropdown(true) }) .catch(() => setLocationResults([])) .finally(() => setLocationSearching(false)) }, []) useEffect(() => { const query = formData.location.trim() if (query.length < 2 || !selectedCountryId) { setLocationResults([]) setShowLocationDropdown(false) return } const timer = setTimeout(() => searchLocation(query, selectedCountryId), 350) return () => clearTimeout(timer) }, [formData.location, selectedCountryId, searchLocation]) useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if (locationRef.current && !locationRef.current.contains(e.target as Node)) { setShowLocationDropdown(false) } } document.addEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside) }, []) const set = (field: string, value: string | boolean) => setFormData((prev) => ({ ...prev, [field]: value })) const canSubmit = formData.title.trim().length >= 5 && formData.description.trim().length >= 20 && formData.companyId !== "" 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, ...(locationIds.cityId && { cityId: locationIds.cityId }), ...(locationIds.regionId && { regionId: locationIds.regionId }), employmentType: (formData.employmentType as CreateJobPayload["employmentType"]) || undefined, workMode: (formData.workMode as CreateJobPayload["workMode"]) || undefined, workingHours: formData.workingHours || 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, salaryNegotiable: formData.salaryNegotiable, languageLevel: formData.languageLevel || undefined, visaSupport: formData.visaSupport, requirements: { resumeRequirement: formData.resumeRequirement, applicationChannel: formData.applicationChannel, applicationEmail: formData.applicationChannel === "email" ? formData.applicationEmail : null, applicationUrl: formData.applicationChannel === "url" ? formData.applicationUrl : null, applicationPhone: formData.applicationChannel === "phone" ? formData.applicationPhone : null, }, status: formData.status as CreateJobPayload["status"], } await jobsApi.create(payload) toast.success("Vaga cadastrada com sucesso!") setFormData({ companyId: "", title: "", description: "", location: "", country: "", employmentType: "", workMode: "", workingHours: "", salaryMin: "", salaryMax: "", salaryType: "monthly", currency: "BRL", salaryNegotiable: false, languageLevel: "", applicationChannel: "email", applicationEmail: "", applicationUrl: "", applicationPhone: "", resumeRequirement: "optional", visaSupport: false, status: "draft", }) setLocationIds({ cityId: null, regionId: null }) } catch (error: any) { toast.error(error.message || "Falha ao cadastrar vaga") } finally { setLoading(false) } } return (

Nova vaga

Preencha os dados da vaga. Os campos marcados com * são obrigatórios.

{/* Empresa e Status */} Empresa e status
{loadingCompanies ? (
Carregando...
) : ( )}
{/* Dados da vaga */} Dados da vaga
set("title", e.target.value)} />

{formData.title.length}/255 caracteres