import React, {useMemo, useRef, useState} from 'react' import Select from 'react-select' import {DayPicker} from 'react-day-picker' import 'react-day-picker/dist/style.css' import {searchJobOptions} from '../api/jobs.js' import { formatDate } from '../utils/date.js' export function FiltersBar({value, onChange, domain, onRefresh, lastUpdatedAt, nextPlannedAt, onSubmit, onClear, isLoading}) { function set(partial) { onChange({...value, ...partial}) } const hasAny = useMemo(() => { return Boolean( value.titles.length || value.companies.length || value.locations.length || value.salaryMin !== '' || value.salaryMax !== '' || value.top || value.dateFrom || value.dateTo ) }, [value]) const [openCalendar, setOpenCalendar] = useState(false) const selectStyles = { control: (base) => ({ ...base, minHeight: 44, backgroundColor: 'rgba(255,255,255,0.06)', borderColor: 'rgba(255,255,255,0.2)', color: 'white', boxShadow: 'none', }), menu: (base) => ({ ...base, backgroundColor: '#171d28', color: 'white', border: '1px solid rgba(255,255,255,0.12)' }), menuPortal: (base) => ({...base, zIndex: 60}), singleValue: (base) => ({...base, color: 'white'}), input: (base) => ({...base, color: 'white'}), multiValue: (base) => ({...base, backgroundColor: 'rgba(183,116,255,0.25)'}), multiValueLabel: (base) => ({...base, color: 'white'}), multiValueRemove: (base) => ({ ...base, color: 'white', ':hover': {backgroundColor: 'rgba(183,116,255,0.4)', color: '#0b0c10'} }), option: (base, s) => ({ ...base, background: s.isSelected ? 'rgba(183,116,255,0.25)' : s.isFocused ? 'rgba(255,255,255,0.08)' : 'transparent', color: 'white' }), } const [titleOptions, setTitleOptions] = useState([]) const [companyOptions, setCompanyOptions] = useState([]) const [locationOptions, setLocationOptions] = useState([]) const debounceIdRef = useRef(null) async function loadOptions(field, query, setter) { try { const api = await searchJobOptions(field, query) const arr = api?.data?.data || [] setter(arr.map(v => ({value: v, label: v}))) } catch (e) { setter([]) } } function handleMenuOpen(field, setter) { loadOptions(field, '', setter) } function handleInputChange(field, setter) { return (inputValue, meta) => { if (meta.action === 'input-change') { if (debounceIdRef.current) clearTimeout(debounceIdRef.current) debounceIdRef.current = setTimeout(() => { loadOptions(field, inputValue || '', setter) }, 500) } return inputValue } } return (
Last update: {isLoading ? : lastUpdatedAt}
Next planned: {isLoading ? : nextPlannedAt}
{hasAny && (
)}
({value: v, label: v}))} onChange={vals => set({companies: vals.map(v => v.value)})} onMenuOpen={() => handleMenuOpen('company', setCompanyOptions)} onInputChange={handleInputChange('company', setCompanyOptions)} styles={selectStyles} classNamePrefix="rs" menuPortalTarget={document.body}/>
set({salaryMin: e.target.value})} disabled={isLoading} className="mt-1 h-[44px] w-full px-3 rounded-lg bg-white/5 border border-white/10 outline-none focus:border-[var(--color-primary)] disabled:opacity-60"/>
set({salaryMax: e.target.value})} disabled={isLoading} className="mt-1 h-[44px] w-full px-3 rounded-lg bg-white/5 border border-white/10 outline-none focus:border-[var(--color-primary)] disabled:opacity-60"/>
set({top: e.target.checked})} disabled={isLoading} className="size-5 accent-[var(--color-primary-600)]"/> Only top 5
{openCalendar && (
{ let from = range?.from ?? null let to = range?.to ?? null const isSameDay = from && to && from.toDateString() === to.toDateString() if (isSameDay) { to = null } set({dateFrom: from, dateTo: to}) if (from && to && !isSameDay) setOpenCalendar(false) }} styles={{ caption: {color: 'white'}, day: {color: 'white'}, day_selected: {backgroundColor: '#8f8cf8', color: '#0b0c10'}, day_range_start: {backgroundColor: '#7a76f2', color: '#0b0c10'}, day_range_end: {backgroundColor: '#7a76f2', color: '#0b0c10'}, day_range_middle: {backgroundColor: 'rgba(143,140,248,0.4)', color: 'white'}, }} />
)}
) }