|
|
@ -10,13 +10,14 @@ import {
|
|
|
|
PlusIcon,
|
|
|
|
PlusIcon,
|
|
|
|
} from '@heroicons/react/20/solid';
|
|
|
|
} from '@heroicons/react/20/solid';
|
|
|
|
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
|
|
|
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
|
|
|
import { Tabs, TextInput } from '@tih/ui';
|
|
|
|
import { CheckboxInput, CheckboxList, Tabs, TextInput } from '@tih/ui';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import type { FilterOption } from '~/components/resumes/browse/resumeConstants';
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
BROWSE_TABS_VALUES,
|
|
|
|
BROWSE_TABS_VALUES,
|
|
|
|
EXPERIENCE,
|
|
|
|
EXPERIENCE,
|
|
|
|
LOCATION,
|
|
|
|
LOCATION,
|
|
|
|
ROLES,
|
|
|
|
ROLE,
|
|
|
|
SORT_OPTIONS,
|
|
|
|
SORT_OPTIONS,
|
|
|
|
TOP_HITS,
|
|
|
|
TOP_HITS,
|
|
|
|
} from '~/components/resumes/browse/resumeConstants';
|
|
|
|
} from '~/components/resumes/browse/resumeConstants';
|
|
|
@ -29,11 +30,19 @@ import { trpc } from '~/utils/trpc';
|
|
|
|
|
|
|
|
|
|
|
|
import type { Resume } from '~/types/resume';
|
|
|
|
import type { Resume } from '~/types/resume';
|
|
|
|
|
|
|
|
|
|
|
|
const filters = [
|
|
|
|
type FilterId = 'experience' | 'location' | 'role';
|
|
|
|
|
|
|
|
type Filter = {
|
|
|
|
|
|
|
|
id: FilterId;
|
|
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
|
|
options: Array<FilterOption>;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
type FilterState = Record<FilterId, Array<string>>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const filters: Array<Filter> = [
|
|
|
|
{
|
|
|
|
{
|
|
|
|
id: 'roles',
|
|
|
|
id: 'role',
|
|
|
|
name: 'Roles',
|
|
|
|
name: 'Role',
|
|
|
|
options: ROLES,
|
|
|
|
options: ROLE,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
{
|
|
|
|
id: 'experience',
|
|
|
|
id: 'experience',
|
|
|
@ -47,11 +56,35 @@ const filters = [
|
|
|
|
},
|
|
|
|
},
|
|
|
|
];
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const INITIAL_FILTER_STATE: FilterState = {
|
|
|
|
|
|
|
|
experience: Object.values(EXPERIENCE).map(({ value }) => value),
|
|
|
|
|
|
|
|
location: Object.values(LOCATION).map(({ value }) => value),
|
|
|
|
|
|
|
|
role: Object.values(ROLE).map(({ value }) => value),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const filterResumes = (
|
|
|
|
|
|
|
|
resumes: Array<Resume>,
|
|
|
|
|
|
|
|
searchValue: string,
|
|
|
|
|
|
|
|
userFilters: FilterState,
|
|
|
|
|
|
|
|
) => {
|
|
|
|
|
|
|
|
return resumes
|
|
|
|
|
|
|
|
.filter((resume) =>
|
|
|
|
|
|
|
|
resume.title.toLowerCase().includes(searchValue.toLocaleLowerCase()),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
.filter(
|
|
|
|
|
|
|
|
({ experience, location, role }) =>
|
|
|
|
|
|
|
|
userFilters.role.includes(role) &&
|
|
|
|
|
|
|
|
userFilters.experience.includes(experience) &&
|
|
|
|
|
|
|
|
userFilters.location.includes(location),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default function ResumeHomePage() {
|
|
|
|
export default function ResumeHomePage() {
|
|
|
|
const { data: sessionData } = useSession();
|
|
|
|
const { data: sessionData } = useSession();
|
|
|
|
const router = useRouter();
|
|
|
|
const router = useRouter();
|
|
|
|
const [tabsValue, setTabsValue] = useState(BROWSE_TABS_VALUES.ALL);
|
|
|
|
const [tabsValue, setTabsValue] = useState(BROWSE_TABS_VALUES.ALL);
|
|
|
|
const [searchValue, setSearchValue] = useState('');
|
|
|
|
const [searchValue, setSearchValue] = useState('');
|
|
|
|
|
|
|
|
const [userFilters, setUserFilters] = useState(INITIAL_FILTER_STATE);
|
|
|
|
const [resumes, setResumes] = useState<Array<Resume>>([]);
|
|
|
|
const [resumes, setResumes] = useState<Array<Resume>>([]);
|
|
|
|
const [renderSignInButton, setRenderSignInButton] = useState(false);
|
|
|
|
const [renderSignInButton, setRenderSignInButton] = useState(false);
|
|
|
|
const [signInButtonText, setSignInButtonText] = useState('');
|
|
|
|
const [signInButtonText, setSignInButtonText] = useState('');
|
|
|
@ -102,6 +135,26 @@ export default function ResumeHomePage() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onFilterCheckboxChange = (
|
|
|
|
|
|
|
|
isChecked: boolean,
|
|
|
|
|
|
|
|
filterSection: FilterId,
|
|
|
|
|
|
|
|
filterValue: string,
|
|
|
|
|
|
|
|
) => {
|
|
|
|
|
|
|
|
if (isChecked) {
|
|
|
|
|
|
|
|
setUserFilters({
|
|
|
|
|
|
|
|
...userFilters,
|
|
|
|
|
|
|
|
[filterSection]: [...userFilters[filterSection], filterValue],
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
setUserFilters({
|
|
|
|
|
|
|
|
...userFilters,
|
|
|
|
|
|
|
|
[filterSection]: userFilters[filterSection].filter(
|
|
|
|
|
|
|
|
(value) => value !== filterValue,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
<Head>
|
|
|
|
<Head>
|
|
|
@ -256,8 +309,8 @@ export default function ResumeHomePage() {
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</Disclosure.Button>
|
|
|
|
</Disclosure.Button>
|
|
|
|
</h3>
|
|
|
|
</h3>
|
|
|
|
<Disclosure.Panel className="pt-6">
|
|
|
|
<Disclosure.Panel className="pt-4">
|
|
|
|
<div className="space-y-4">
|
|
|
|
{/* <div className="space-y-4">
|
|
|
|
{section.options.map((option, optionIdx) => (
|
|
|
|
{section.options.map((option, optionIdx) => (
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
key={option.value}
|
|
|
|
key={option.value}
|
|
|
@ -269,6 +322,7 @@ export default function ResumeHomePage() {
|
|
|
|
id={`filter-${section.id}-${optionIdx}`}
|
|
|
|
id={`filter-${section.id}-${optionIdx}`}
|
|
|
|
name={`${section.id}[]`}
|
|
|
|
name={`${section.id}[]`}
|
|
|
|
type="checkbox"
|
|
|
|
type="checkbox"
|
|
|
|
|
|
|
|
onChange={(value) => console.log(value)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
<label
|
|
|
|
<label
|
|
|
|
className="ml-3 text-sm text-gray-600"
|
|
|
|
className="ml-3 text-sm text-gray-600"
|
|
|
@ -277,7 +331,32 @@ export default function ResumeHomePage() {
|
|
|
|
</label>
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</div> */}
|
|
|
|
|
|
|
|
<CheckboxList
|
|
|
|
|
|
|
|
description=""
|
|
|
|
|
|
|
|
isLabelHidden={true}
|
|
|
|
|
|
|
|
label=""
|
|
|
|
|
|
|
|
orientation="vertical">
|
|
|
|
|
|
|
|
{section.options.map((option) => (
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
key={option.value}
|
|
|
|
|
|
|
|
className="[&>div>div:nth-child(2)>label]:font-normal [&>div>div:nth-child(1)>input]:text-indigo-600 [&>div>div:nth-child(1)>input]:ring-indigo-500">
|
|
|
|
|
|
|
|
<CheckboxInput
|
|
|
|
|
|
|
|
label={option.label}
|
|
|
|
|
|
|
|
value={userFilters[section.id].includes(
|
|
|
|
|
|
|
|
option.value,
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
onChange={(isChecked) =>
|
|
|
|
|
|
|
|
onFilterCheckboxChange(
|
|
|
|
|
|
|
|
isChecked,
|
|
|
|
|
|
|
|
section.id,
|
|
|
|
|
|
|
|
option.value,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
</CheckboxList>
|
|
|
|
</Disclosure.Panel>
|
|
|
|
</Disclosure.Panel>
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
)}
|
|
|
@ -296,7 +375,7 @@ export default function ResumeHomePage() {
|
|
|
|
starredResumesQuery.isFetching ||
|
|
|
|
starredResumesQuery.isFetching ||
|
|
|
|
myResumesQuery.isFetching
|
|
|
|
myResumesQuery.isFetching
|
|
|
|
}
|
|
|
|
}
|
|
|
|
resumes={resumes}
|
|
|
|
resumes={filterResumes(resumes, searchValue, userFilters)}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|