feat: add advanced filters UI to jobs page

Frontend:
- Add salaryMin, salaryMax, currencyFilter, visaSupport state
- Enable sortBy dropdown with 4 options (recent, salary_desc, salary_asc, relevance)
- Add currency filter (BRL, USD, EUR, JPY)
- Update api.ts jobsApi.list with new filter params
- Fix employmentType query param name (was 'type')

All filters now match backend API endpoints
This commit is contained in:
Tiago Yamamoto 2025-12-24 11:46:12 -03:00
parent 9a4e469a18
commit 246c55b0f5
2 changed files with 48 additions and 4 deletions

View file

@ -32,9 +32,15 @@ function JobsContent() {
const [locationFilter, setLocationFilter] = useState("")
const [typeFilter, setTypeFilter] = useState("all")
const [workModeFilter, setWorkModeFilter] = useState("all")
const [sortBy, setSortBy] = useState("recent") // Client-side sort or ignore? Backend doesn't support sort yet generally.
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)
@ -82,6 +88,11 @@ function JobsContent() {
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
@ -121,6 +132,11 @@ function JobsContent() {
setLocationFilter("")
setTypeFilter("all")
setWorkModeFilter("all")
setSalaryMin("")
setSalaryMax("")
setCurrencyFilter("all")
setVisaSupport(false)
setSortBy("recent")
}
const getTypeLabel = (type: string) => {
@ -244,13 +260,29 @@ function JobsContent() {
</SelectContent>
</Select>
<Select value={sortBy} onValueChange={setSortBy} disabled>
<Select value={sortBy} onValueChange={setSortBy}>
<SelectTrigger>
<ArrowUpDown className="h-4 w-4 mr-2" />
<SelectValue placeholder={t('jobs.filters.order')} />
</SelectTrigger>
<SelectContent>
<SelectItem value="recent">{t('jobs.sort.recent')}</SelectItem>
<SelectItem value="recent">{t('jobs.sort.recent') || 'Mais recentes'}</SelectItem>
<SelectItem value="salary_desc">{t('jobs.sort.salaryDesc') || 'Maior salário'}</SelectItem>
<SelectItem value="salary_asc">{t('jobs.sort.salaryAsc') || 'Menor salário'}</SelectItem>
<SelectItem value="relevance">{t('jobs.sort.relevance') || 'Relevância'}</SelectItem>
</SelectContent>
</Select>
<Select value={currencyFilter} onValueChange={setCurrencyFilter}>
<SelectTrigger>
<SelectValue placeholder="Moeda" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">Todas moedas</SelectItem>
<SelectItem value="BRL">R$ (BRL)</SelectItem>
<SelectItem value="USD">$ (USD)</SelectItem>
<SelectItem value="EUR"> (EUR)</SelectItem>
<SelectItem value="JPY">¥ (JPY)</SelectItem>
</SelectContent>
</Select>

View file

@ -313,15 +313,27 @@ export const jobsApi = {
type?: string;
workMode?: string;
companyId?: string;
// Advanced filters
salaryMin?: number;
salaryMax?: number;
currency?: string;
visaSupport?: boolean;
sortBy?: string;
}) => {
const query = new URLSearchParams();
if (params.page) query.append("page", params.page.toString());
if (params.limit) query.append("limit", params.limit.toString());
if (params.q) query.append("q", params.q);
if (params.location) query.append("location", params.location);
if (params.type) query.append("type", params.type);
if (params.type) query.append("employmentType", params.type);
if (params.workMode) query.append("workMode", params.workMode);
if (params.companyId) query.append("companyId", params.companyId);
// Advanced filters
if (params.salaryMin) query.append("salaryMin", params.salaryMin.toString());
if (params.salaryMax) query.append("salaryMax", params.salaryMax.toString());
if (params.currency) query.append("currency", params.currency);
if (params.visaSupport) query.append("visaSupport", "true");
if (params.sortBy) query.append("sortBy", params.sortBy);
return apiRequest<{
data: ApiJob[];