"use client" import { useSearchParams } from "next/navigation" import { useEffect, useState, useMemo, Suspense } from "react" import { Navbar } from "@/components/navbar" import { Footer } from "@/components/footer" import { JobCard } from "@/components/job-card" import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Badge } from "@/components/ui/badge" import { Card, CardContent } from "@/components/ui/card" import { PageSkeleton } from "@/components/loading-skeletons" import { jobsApi, transformApiJobToFrontend } from "@/lib/api" import { useDebounce } from "@/hooks/use-utils" import { useTranslation } from "@/lib/i18n" import { Search, MapPin, Briefcase, SlidersHorizontal, X, ArrowUpDown } from "lucide-react" import { motion, AnimatePresence } from "framer-motion" import type { Job } from "@/lib/types" function JobsContent() { const { t } = useTranslation() const searchParams = useSearchParams() // State const [jobs, setJobs] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) // Filters state const [searchTerm, setSearchTerm] = useState("") const [locationFilter, setLocationFilter] = useState("") const [typeFilter, setTypeFilter] = useState("all") const [workModeFilter, setWorkModeFilter] = useState("all") const [sortBy, setSortBy] = useState("recent") const [showFilters, setShowFilters] = useState(false) // Advanced filters const [salaryMin, setSalaryMin] = useState("") const [salaryMax, setSalaryMax] = useState("") const [currencyFilter, setCurrencyFilter] = useState("all") const [visaSupport, setVisaSupport] = useState(false) // Pagination state const [currentPage, setCurrentPage] = useState(1) const [totalJobs, setTotalJobs] = useState(0) const ITEMS_PER_PAGE = 10 // Optimize search inputs const debouncedSearchTerm = useDebounce(searchTerm, 500) const debouncedLocation = useDebounce(locationFilter, 500) // Initial params useEffect(() => { const tech = searchParams.get("tech") const q = searchParams.get("q") const s = searchParams.get("s") const type = searchParams.get("type") const location = searchParams.get("location") const l = searchParams.get("l") const mode = searchParams.get("mode") const workMode = searchParams.get("workMode") if (tech || q || s) { setSearchTerm(tech || q || s || "") setShowFilters(true) } if (location || l) { setLocationFilter(location || l || "") setShowFilters(true) } if (type === "remote") { setWorkModeFilter("remote") setShowFilters(true) } else if (mode || workMode) { setWorkModeFilter(mode || workMode || "all") setShowFilters(true) } }, [searchParams]) // Reset page when filters change (debounced) useEffect(() => { setCurrentPage(1) }, [debouncedSearchTerm, debouncedLocation, typeFilter, workModeFilter]) // Main Fetch Logic useEffect(() => { let isMounted = true const fetchJobs = async () => { setLoading(true) setError(null) try { const response = await jobsApi.list({ page: currentPage, limit: ITEMS_PER_PAGE, q: debouncedSearchTerm || undefined, location: debouncedLocation || undefined, type: typeFilter === "all" ? undefined : typeFilter, workMode: workModeFilter === "all" ? undefined : workModeFilter, salaryMin: salaryMin ? parseFloat(salaryMin) : undefined, salaryMax: salaryMax ? parseFloat(salaryMax) : undefined, currency: currencyFilter === "all" ? undefined : currencyFilter, visaSupport: visaSupport || undefined, sortBy: sortBy || undefined, }) // Transform the raw API response to frontend format const mappedJobs = (response.data || []).map(job => transformApiJobToFrontend(job)); if (isMounted) { setJobs(mappedJobs) setTotalJobs(response.pagination?.total || 0) } } catch (err) { console.error("Error fetching jobs", err) if (isMounted) { setError(t('jobs.error')) setJobs([]) setTotalJobs(0) } } finally { if (isMounted) { setLoading(false) } } } fetchJobs() return () => { isMounted = false } }, [ currentPage, debouncedSearchTerm, debouncedLocation, typeFilter, workModeFilter, salaryMin, salaryMax, currencyFilter, visaSupport, sortBy, t, ]) // Computed const totalPages = Math.ceil(totalJobs / ITEMS_PER_PAGE) const hasActiveFilters = searchTerm || locationFilter || typeFilter !== "all" || workModeFilter !== "all" const clearFilters = () => { setSearchTerm("") setLocationFilter("") setTypeFilter("all") setWorkModeFilter("all") setSalaryMin("") setSalaryMax("") setCurrencyFilter("all") setVisaSupport(false) setSortBy("recent") } const getTypeLabel = (type: string) => { const label = t(`jobs.types.${type}`) return label !== `jobs.types.${type}` ? label : type } // Hardcoded options since we don't have all data client-side const workModeOptions = ["remote", "hybrid", "onsite"] const typeOptions = ["full-time", "part-time", "contract", "dispatch"] return ( <> {/* Hero Section */}
{/* Imagem de fundo Vagas.jpg sem opacidade */}
Vagas
{/* Overlay preto com opacidade 20% */}
{t('jobs.title')} {loading ? t('jobs.loading') : t('jobs.subtitle', { count: totalJobs })}
{/* Search and Filters Section */}
{/* Main Search Bar */}
setSearchTerm(e.target.value)} className="pl-10 h-12" />
setLocationFilter(e.target.value)} className="pl-10 h-12" />
{/* Advanced Filters */} {showFilters && (
{hasActiveFilters && ( )}
)}
{/* Results Summary */}
{t('jobs.pagination.showing', { from: Math.min((currentPage - 1) * ITEMS_PER_PAGE + 1, totalJobs), to: Math.min(currentPage * ITEMS_PER_PAGE, totalJobs), total: totalJobs })} {hasActiveFilters && (
Active filters: {searchTerm && ( "{searchTerm}" )} {locationFilter && ( {locationFilter} )} {typeFilter !== "all" && ( {typeFilter} )} {workModeFilter !== "all" && ( {workModeFilter === "remote" ? t("workMode.remote") : workModeFilter === "hybrid" ? t("workMode.hybrid") : workModeFilter === "onsite" ? t("workMode.onsite") : workModeFilter} )}
)}
{/* Jobs Grid */}
{error && (
{error}
)} {loading ? ( ) : jobs.length > 0 ? (
{jobs.map((job, index) => ( ))} {/* Pagination Controls */} {totalPages > 1 && (
{currentPage} / {totalPages}
)}
) : (

{t('jobs.noResults.title')}

{t('jobs.noResults.desc')}

)}
) } export default function JobsPage() { return (
}>
) }