Skip to content

Commit

Permalink
OPHJOD-1067: Add filters and sorting to tool
Browse files Browse the repository at this point in the history
  • Loading branch information
juhaniko committed Dec 4, 2024
1 parent d46dd82 commit b313aa2
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 75 deletions.
4 changes: 4 additions & 0 deletions src/components/OsaamisSuosittelija/OsaamisSuosittelija.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ export const OsaamisSuosittelija = ({
title={getLocalizedText(ehdotettuOsaaminen.kuvaus)}
sourceType={mode === 'osaamiset' ? OSAAMINEN_COLOR_MAP[sourceType] : OSAAMINEN_COLOR_MAP['KIINNOSTUS']}
onClick={() => {
if (ehdotettuOsaaminen.id && value.find((val) => val.id === ehdotettuOsaaminen.id)) {
return; // Prevent adding duplicates by rapid clicking
}

onChange([
...value,
{
Expand Down
14 changes: 13 additions & 1 deletion src/i18n/fi/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"date-placeholder": "pp.kk.vvvv",
"delete": "Poista",
"development-trend": "Kehitystrendi",
"do-filter": "Suodata",
"edit": "Muokkaa",
"education-history": {
"add-new-degree": "Lisää uusi tutkinto",
Expand Down Expand Up @@ -239,7 +240,6 @@
"competences": {
"add": "Lisää osaamisia",
"description": "Löydät alta kaikki osaamisesi, jotka olet tunnistanut tai lisännyt profiiliisi. Osaamisesi ryhmittelyn ja esitystavan voit valita itse.",
"do-filter": "Suodata",
"edit": "Muokkaa osaamisia",
"group": "Järjestele",
"group-by-alphabet": "Aakkosellisesti",
Expand Down Expand Up @@ -439,6 +439,18 @@
"description": "Voit säätää osaamisten ja kiinnostusten painotusta tuloksissa."
},
"description": "Alla näet palvelun tunnistamia työ- ja koulutusmahdollisuuksia tietojesi pohjalta.",
"filters": {
"education-opportunities": "Koulutusmahdollisuudet",
"job-and-education-opportunities": "Työ- ja koulutusmahdollisuudet",
"job-opportunities": "Työmahdollisuudet",
"title": "Näytä mahdollisuuksissa"
},
"n-opportunities-found": "Löysimme {{count}} mahdollisuutta.",
"sorting": {
"alphabetically": "Aakkosjärjestyksessä",
"by-relevance": "Sopivimmat",
"title": "Järjestele mahdollisuudet"
},
"title": "Mahdollisuutesi"
}
},
Expand Down
8 changes: 2 additions & 6 deletions src/routes/Profile/Competences/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const TitleCheckbox = ({ type, checked, onChange }: TitleCheckboxProps) => {
checked={checked}
onChange={onChange}
ariaLabel={t(`types.competence.${type}`)}
name={t('profile.competences.do-filter')}
name={t('do-filter')}
value={type}
className="min-h-7"
/>
Expand Down Expand Up @@ -98,11 +98,7 @@ export const Filters = ({ groupBy, setGroupBy, filterKeys, selectedFilters, setS
<RadioButton label={t('profile.competences.group-by-alphabet')} value={GROUP_BY_ALPHABET} />
</RadioButtonGroup>
</SimpleNavigationList>
<SimpleNavigationList
title={t('profile.competences.do-filter')}
backgroundClassName={sm ? 'bg-bg-gray-2' : 'bg-bg-gray'}
collapsible
>
<SimpleNavigationList title={t('do-filter')} backgroundClassName={sm ? 'bg-bg-gray-2' : 'bg-bg-gray'} collapsible>
<ul className="flex flex-col gap-y-3 py-4">
{filterKeys.map((key) => (
<React.Fragment key={key}>
Expand Down
43 changes: 43 additions & 0 deletions src/routes/Tool/OpportunitiesFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { filterValues, sortingValues } from '@/routes/Tool/utils';
import { useToolStore } from '@/stores/useToolStore';
import { RadioButton, RadioButtonGroup } from '@jod/design-system';
import { useTranslation } from 'react-i18next';

const OpportunitiesFilter = () => {
const { t } = useTranslation();
const { filter, sorting, setFilter, setSorting } = useToolStore();
const filterTitle = t('tool.your-opportunities.filters.title');
const sortingTitle = t('tool.your-opportunities.sorting.title');

return (
<div className="flex flex-col absolute right-0 top-full z-10 bg-bg-gray-2 p-6 rounded-md mt-4 w-[343px] shadow-border text-left gap-6">
<h2 className="text-heading-2">{t('do-filter')}</h2>

<div className="flex flex-col gap-5">
<h3 className="text-heading-3">{filterTitle}</h3>
<RadioButtonGroup label={filterTitle} value={filter} onChange={setFilter} hideLabel>
<RadioButton
label={t('tool.your-opportunities.filters.job-opportunities')}
value={filterValues.TYOMAHDOLLISUUS}
/>
<RadioButton
label={t('tool.your-opportunities.filters.education-opportunities')}
value={filterValues.KOULUTUSMAHDOLLISUUS}
/>
<RadioButton
label={t('tool.your-opportunities.filters.job-and-education-opportunities')}
value={filterValues.ALL}
/>
</RadioButtonGroup>

<h3 className="text-heading-3">{sortingTitle}</h3>
<RadioButtonGroup label={sortingTitle} value={sorting} onChange={setSorting} hideLabel>
<RadioButton label={t('tool.your-opportunities.sorting.alphabetically')} value={sortingValues.ALPHABET} />
<RadioButton label={t('tool.your-opportunities.sorting.by-relevance')} value={sortingValues.RELEVANCE} />
</RadioButtonGroup>
</div>
</div>
);
};

export default OpportunitiesFilter;
29 changes: 26 additions & 3 deletions src/routes/Tool/Tool.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { OpportunityCard, Title } from '@/components';
import { useEnvironment } from '@/hooks/useEnvironment';
import { OpportunitiesFilter } from '@/routes/Tool';
import { MahdollisuusTyyppi } from '@/routes/types';
import { useToolStore } from '@/stores/useToolStore';
import { getLocalizedText } from '@/utils';
import {
Expand All @@ -14,7 +16,7 @@ import {
} from '@jod/design-system';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { MdBlock, MdOutlineInterests, MdOutlineSchool } from 'react-icons/md';
import { MdBlock, MdOutlineInterests, MdOutlineSchool, MdOutlineTune } from 'react-icons/md';
import { Outlet, useLoaderData, useLocation, useNavigate } from 'react-router-dom';
import { ToolLoaderData } from './loader';

Expand Down Expand Up @@ -243,7 +245,7 @@ const YourOpportunitiesCard = ({ scrollRef }: { scrollRef: React.RefObject<HTMLU
return (
<div
id="tool-your-opportunities-card"
className="flex flex-col gap-5 mb-7 p-5 sm:p-6 bg-secondary-1-25 rounded shadow-border z-10"
className="flex flex-col gap-5 mb-6 p-5 sm:p-6 bg-secondary-1-25 rounded shadow-border z-10"
>
<p className="text-body-md-mobile sm:text-body-md">{t('tool.your-opportunities.card.description')}</p>
<Slider
Expand Down Expand Up @@ -280,6 +282,13 @@ const YourOpportunities = () => {
const toolStore = useToolStore();
const scrollRef = React.useRef<HTMLUListElement>(null);
const { isLoggedIn } = useLoaderData() as ToolLoaderData;
const [filtersOpen, setFiltersOpen] = React.useState(false);
const ehdotuksetCount = toolStore.ehdotuksetCount ?? {};
const filter = toolStore.filter;
const count =
filter === 'ALL'
? Object.keys(ehdotuksetCount).reduce((acc, key) => acc + ehdotuksetCount[key as MahdollisuusTyyppi], 0)
: ehdotuksetCount[filter];

return (
<main role="main" className="col-span-3 lg:col-span-1" id="jod-main">
Expand All @@ -288,7 +297,21 @@ const YourOpportunities = () => {

<YourOpportunitiesCard scrollRef={scrollRef} />

<YourOpportunitiesPagination scrollRef={scrollRef} ariaLabel={t('pagination.top')} className="mb-7" />
<div className="mb-6 flex justify-between items-center">
<span className="font-arial text-form-label">
{t('tool.your-opportunities.n-opportunities-found', { count })}
</span>
<button
className="text-form-label flex flex-row items-center gap-5"
onClick={() => setFiltersOpen(!filtersOpen)}
>
<span className="font-arial">{t('do-filter')}</span>
<span className="flex bg-white rounded-full relative size-7 justify-center items-center">
<MdOutlineTune size={20} />
{filtersOpen && <OpportunitiesFilter />}
</span>
</button>
</div>

<ul
id="tool-your-opportunities-list"
Expand Down
5 changes: 3 additions & 2 deletions src/routes/Tool/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Competences from './Competences';
import Goals from './Goals';
import Interests from './Interests';
import loader from './loader';
import OpportunitiesFilter from './OpportunitiesFilter';
import Restrictions from './Restrictions';
import Tool from './Tool';
import loader from './loader';

export { Competences, Goals, Interests, Restrictions, Tool, loader as toolLoader };
export { Competences, Goals, Interests, OpportunitiesFilter, Restrictions, Tool, loader as toolLoader };
16 changes: 16 additions & 0 deletions src/routes/Tool/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,19 @@ export const ehdotusDataToRecord = (array: components['schemas']['EhdotusDto'][]
return acc;
}, {} as EhdotusRecord);
};

export type OpportunityFilterValue = components['schemas']['EhdotusMetadata']['tyyppi'] | 'ALL';
export type OpportunitySortingValue = 'ALPHABET' | 'RELEVANCE';
export const filterValues: Record<OpportunityFilterValue, OpportunityFilterValue> = {
ALL: 'ALL',
KOULUTUSMAHDOLLISUUS: 'KOULUTUSMAHDOLLISUUS',
TYOMAHDOLLISUUS: 'TYOMAHDOLLISUUS',
} as const;

export const sortingValues: Record<OpportunitySortingValue, OpportunitySortingValue> = {
ALPHABET: 'ALPHABET',
RELEVANCE: 'RELEVANCE',
} as const;

export const DEFAULT_FILTER = filterValues.ALL;
export const DEFAULT_SORTING = sortingValues.RELEVANCE;
Loading

0 comments on commit b313aa2

Please sign in to comment.