diff --git a/frontend/src/app/jobs/page.tsx b/frontend/src/app/jobs/page.tsx index 255c005..3d00364 100644 --- a/frontend/src/app/jobs/page.tsx +++ b/frontend/src/app/jobs/page.tsx @@ -1,6 +1,6 @@ "use client" -import { useSearchParams } from "next/navigation" +import { usePathname, useRouter, useSearchParams } from "next/navigation" import { useEffect, useState, useMemo, Suspense, useCallback } from "react" import { Navbar } from "@/components/navbar" import { Footer } from "@/components/footer" @@ -19,8 +19,13 @@ import { Search, MapPin, Briefcase, SlidersHorizontal, X, ArrowUpDown, Clock, Be import { motion, AnimatePresence } from "framer-motion" import type { Job } from "@/lib/types" +const WORK_MODE_OPTIONS = ["remote", "hybrid", "onsite"] +const TYPE_OPTIONS = ["full-time", "part-time", "contract", "dispatch"] + function JobsContent() { const { t } = useTranslation() + const router = useRouter() + const pathname = usePathname() const searchParams = useSearchParams() const { searches, saveSearch, clearSearches, removeSearch } = useRecentSearches() @@ -55,6 +60,17 @@ function JobsContent() { const debouncedLocation = useDebounce(locationFilter, 500) const handleSearch = useCallback(() => { + const query = new URLSearchParams() + + if (searchTerm.trim()) query.set("q", searchTerm.trim()) + if (locationFilter.trim()) query.set("location", locationFilter.trim()) + if (typeFilter !== "all") query.set("type", typeFilter) + if (workModeFilter !== "all") query.set("workMode", workModeFilter) + if (salaryMin.trim()) query.set("salary", salaryMin.trim()) + + const nextUrl = query.toString() ? `${pathname}?${query.toString()}` : pathname + router.replace(nextUrl, { scroll: false }) + if (searchTerm || locationFilter) { saveSearch({ query: searchTerm, @@ -66,7 +82,17 @@ function JobsContent() { }, }) } - }, [searchTerm, locationFilter, typeFilter, workModeFilter, datePostedFilter, saveSearch]) + }, [ + searchTerm, + locationFilter, + typeFilter, + workModeFilter, + datePostedFilter, + salaryMin, + pathname, + router, + saveSearch, + ]) // Initial params useEffect(() => { @@ -74,10 +100,17 @@ function JobsContent() { const q = searchParams.get("q") const s = searchParams.get("s") const type = searchParams.get("type") + const contractType = searchParams.get("contractType") const location = searchParams.get("location") const l = searchParams.get("l") const mode = searchParams.get("mode") const workMode = searchParams.get("workMode") + const salary = searchParams.get("salary") + const salaryMinParam = searchParams.get("salaryMin") + + const rawType = (type || contractType || "").toLowerCase() + const rawWorkMode = (mode || workMode || "").toLowerCase() + const parsedSalary = (salaryMinParam || salary || "").replace(/[^\d.,]/g, "").replace(",", ".") if (tech || q || s) { setSearchTerm(tech || q || s || "") @@ -89,11 +122,21 @@ function JobsContent() { setShowFilters(true) } - if (type === "remote") { + if (rawType === "remote") { setWorkModeFilter("remote") setShowFilters(true) - } else if (mode || workMode) { - setWorkModeFilter(mode || workMode || "all") + } else if (rawWorkMode && WORK_MODE_OPTIONS.includes(rawWorkMode)) { + setWorkModeFilter(rawWorkMode) + setShowFilters(true) + } + + if (rawType && TYPE_OPTIONS.includes(rawType)) { + setTypeFilter(rawType) + setShowFilters(true) + } + + if (parsedSalary) { + setSalaryMin(parsedSalary) setShowFilters(true) } }, [searchParams]) @@ -194,8 +237,8 @@ function JobsContent() { } // Hardcoded options since we don't have all data client-side - const workModeOptions = ["remote", "hybrid", "onsite"] - const typeOptions = ["full-time", "part-time", "contract", "dispatch"] + const workModeOptions = WORK_MODE_OPTIONS + const typeOptions = TYPE_OPTIONS return ( <> @@ -264,7 +307,7 @@ function JobsContent() { /> -