Skip to content

Commit

Permalink
OPHJOD-1133: Change alphabetical filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
markus-boman-elenium committed Dec 18, 2024
1 parent 0409628 commit b9ac18f
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 42 deletions.
10 changes: 8 additions & 2 deletions src/api/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,8 @@ export interface components {
trendi?: 'NOUSEVA' | 'LASKEVA';
/** Format: int32 */
tyollisyysNakyma?: number;
/** Format: int32 */
aakkosIndeksi: number;
};
SivuDtoTyomahdollisuusDto: {
sisalto: components['schemas']['TyomahdollisuusDto'][];
Expand Down Expand Up @@ -1612,8 +1614,12 @@ export interface operations {
};
mahdollisuudetCreateEhdotus: {
parameters: {
query?: never;
header?: never;
query?: {
sort?: 'ASC' | 'DESC';
};
header?: {
'Content-Language'?: 'fi' | 'sv' | 'en';
};
path?: never;
cookie?: never;
};
Expand Down
4 changes: 2 additions & 2 deletions src/routes/Tool/Tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ const YourOpportunitiesPagination = ({
}
};

return toolStore.tyomahdollisuudet.length > 0 ? (
return toolStore.mixedMahdollisuudet.length > 0 ? (
<div className={className}>
<Pagination
currentPage={toolStore.ehdotuksetPageNr}
Expand All @@ -198,7 +198,7 @@ const YourOpportunitiesPagination = ({
nextTriggerLabel: t('pagination.next'),
prevTriggerLabel: t('pagination.previous'),
}}
totalItems={toolStore.ehdotuksetCount.KOULUTUSMAHDOLLISUUS + toolStore.ehdotuksetCount.TYOMAHDOLLISUUS}
totalItems={toolStore.itemCount}
onPageChange={(data) => void onPageChange(data)}
/>
</div>
Expand Down
126 changes: 88 additions & 38 deletions src/stores/useToolStore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ interface ToolState {
ehdotuksetCount: Record<MahdollisuusTyyppi, number>;
sorting: OpportunitySortingValue;
filter: OpportunityFilterValue;
itemCount: number;
previousEhdotusUpdateLang: string;
reset: () => void;

setTavoitteet: (state: ToolState['tavoitteet']) => void;
Expand All @@ -59,12 +61,13 @@ interface ToolState {
setOsaamisKiinnostusPainotus: (state: number) => void;
setRajoitePainotus: (state: number) => void;

updateEhdotukset: (signal?: AbortSignal) => Promise<void>;
updateEhdotukset: (lang: string, signal?: AbortSignal) => Promise<void>;
fetchMahdollisuudetPage: (signal?: AbortSignal, page?: number) => Promise<void>;
updateEhdotuksetAndTyomahdollisuudet: () => Promise<void>;

setSorting: (state: string) => void;
setFilter: (state: string) => void;
updateItemCount: () => void;
}

export const useToolStore = create<ToolState>()(
Expand All @@ -89,6 +92,8 @@ export const useToolStore = create<ToolState>()(
ehdotuksetCount: { TYOMAHDOLLISUUS: 0, KOULUTUSMAHDOLLISUUS: 0 },
sorting: DEFAULT_SORTING,
filter: DEFAULT_FILTER,
itemCount: 0,
previousEhdotusUpdateLang: '',
reset: () => {
set({
tavoitteet: {},
Expand All @@ -98,6 +103,7 @@ export const useToolStore = create<ToolState>()(
tyomahdollisuudet: [],
koulutusmahdollisuudet: [],
mixedMahdollisuudet: [],
itemCount: 0,
});
},

Expand All @@ -115,7 +121,7 @@ export const useToolStore = create<ToolState>()(
setRajoitePainotus: (state: number) => {
set({ rajoitePainotus: state });
},
updateEhdotukset: async (signal?: AbortSignal) => {
updateEhdotukset: async (lang: string, signal?: AbortSignal) => {
const { osaamiset, kiinnostukset, osaamisKiinnostusPainotus, rajoitePainotus } = get();

set({ ehdotuksetLoading: true });
Expand All @@ -129,6 +135,7 @@ export const useToolStore = create<ToolState>()(
rajoitePainotus: rajoitePainotus / 100,
},
signal,
headers: { 'Content-Language': lang },
});

const mahdollisuusEhdotukset = ehdotusDataToRecord(mahdollisuusData ?? []);
Expand Down Expand Up @@ -157,23 +164,23 @@ export const useToolStore = create<ToolState>()(
}
},
fetchMahdollisuudetPage: async (signal, newPage = 1) => {
const { filter, ehdotuksetPageSize } = get();
const { filter, ehdotuksetPageSize, sorting } = get();
let ehdotukset = get().mahdollisuusEhdotukset;

if (Object.keys(ehdotukset).length === 0) {
await get().updateEhdotukset(signal);
ehdotukset = get().mahdollisuusEhdotukset;
}

const allIds = Object.keys(ehdotukset ?? []);
// apply ID sorting and filter
const allSortedIds = await fetchSortedAndFilteredEhdotusIds(filter);

set({ mahdollisuudetLoading: true });
try {
const sortedMixedMahdollisuudet = [];

// paginate before fetch to fetch only the ids of selected newPage
const pagedIds = paginate(allSortedIds, newPage, ehdotuksetPageSize);

// fetch tyomahdollisuudet of the page
if ([filterValues.ALL, filterValues.TYOMAHDOLLISUUS].includes(filter)) {
const ids = allIds.filter((id) => ehdotukset[id].tyyppi === 'TYOMAHDOLLISUUS');
const tyomahdollisuudet = await fetchTyomahdollisuudet(ids, newPage, ehdotuksetPageSize).then((data) =>
const ids = pagedIds.filter((id) => ehdotukset[id].tyyppi === 'TYOMAHDOLLISUUS');
const tyomahdollisuudet = await fetchTyomahdollisuudet(ids).then((data) =>
data.tyomahdollisuusResults.map(
(tm) => ({ ...tm, mahdollisuusTyyppi: 'TYOMAHDOLLISUUS' }) as TypedMahdollisuus,
),
Expand All @@ -182,13 +189,14 @@ export const useToolStore = create<ToolState>()(
set({ tyomahdollisuudet });
}

// fetch koulutusmahdollisuudet of the page
if ([filterValues.ALL, filterValues.KOULUTUSMAHDOLLISUUS].includes(filter)) {
const ids = allIds.filter((id) => ehdotukset[id].tyyppi === 'KOULUTUSMAHDOLLISUUS');
const koulutusmahdollisuudet = await fetchKoulutusMahdollisuudet(ids, newPage, ehdotuksetPageSize).then(
(data) =>
data.koulutusmahdollisuusResults.map(
(km) => ({ ...km, mahdollisuusTyyppi: 'KOULUTUSMAHDOLLISUUS' }) as TypedMahdollisuus,
),
const ids = pagedIds.filter((id) => ehdotukset[id].tyyppi === 'KOULUTUSMAHDOLLISUUS');

const koulutusmahdollisuudet = await fetchKoulutusMahdollisuudet(ids).then((data) =>
data.koulutusmahdollisuusResults.map(
(km) => ({ ...km, mahdollisuusTyyppi: 'KOULUTUSMAHDOLLISUUS' }) as TypedMahdollisuus,
),
);
sortedMixedMahdollisuudet.push(...koulutusmahdollisuudet);

Expand All @@ -199,10 +207,13 @@ export const useToolStore = create<ToolState>()(
});
}

// Apply final sorting of page items based on selected sorting
sortedMixedMahdollisuudet.sort((a, b) =>
get().sorting === sortingValues.RELEVANCE
? (ehdotukset[b.id]?.pisteet ?? 0) - (ehdotukset[a.id]?.pisteet ?? 0)
: a.otsikko[i18n.language].localeCompare(b.otsikko[i18n.language]),
sorting === sortingValues.RELEVANCE
? // sort by scores
(ehdotukset[b.id]?.pisteet ?? 0) - (ehdotukset[a.id]?.pisteet ?? 0)
: // sort by backend provided lexicalOrder
ehdotukset[a.id].aakkosIndeksi - ehdotukset[b.id].aakkosIndeksi,
);

set({
Expand All @@ -218,18 +229,36 @@ export const useToolStore = create<ToolState>()(
mahdollisuudetLoading: false,
});
}

async function fetchSortedAndFilteredEhdotusIds(filter: OpportunityFilterValue) {
if (Object.keys(ehdotukset).length === 0 || i18n.language !== get().previousEhdotusUpdateLang) {
await get().updateEhdotukset(i18n.language, signal);
ehdotukset = get().mahdollisuusEhdotukset;
set({ previousEhdotusUpdateLang: i18n.language });
}

return Object.entries(ehdotukset ?? [])
.filter(([, meta]) => (filter === 'ALL' ? true : filter === meta.tyyppi))
.sort(([, metadataA], [, metadataB]) =>
sorting === sortingValues.RELEVANCE
? (metadataB?.pisteet ?? 0) - (metadataA?.pisteet ?? 0)
: (metadataA?.aakkosIndeksi ?? 0) - (metadataB?.aakkosIndeksi ?? 0),
)
.map(([key]) => key);
}
},

updateEhdotuksetAndTyomahdollisuudet: async () => {
const { updateEhdotukset, fetchMahdollisuudetPage, updateSuosikit } = get();
const { updateEhdotukset, fetchMahdollisuudetPage, updateSuosikit, updateItemCount } = get();

abortController.abort();
abortController = new AbortController();
const signal = abortController.signal;

await updateEhdotukset(signal);
await updateEhdotukset(i18n.language, signal);
await fetchMahdollisuudetPage(signal, 1);
await updateSuosikit();
updateItemCount();
},

toggleSuosikki: async (suosionKohdeId: string, tyyppi: MahdollisuusTyyppi) => {
Expand Down Expand Up @@ -281,6 +310,21 @@ export const useToolStore = create<ToolState>()(
setFilter: (state) => {
set({ filter: state as OpportunityFilterValue, ehdotuksetPageNr: 1 });
void get().fetchMahdollisuudetPage(abortController.signal, 1);
get().updateItemCount();
},
updateItemCount: () => {
const { filter, ehdotuksetCount } = get();
switch (filter) {
case 'TYOMAHDOLLISUUS':
set({ itemCount: ehdotuksetCount.TYOMAHDOLLISUUS });
break;
case 'KOULUTUSMAHDOLLISUUS':
set({ itemCount: ehdotuksetCount.KOULUTUSMAHDOLLISUUS });
break;
case 'ALL':
set({ itemCount: ehdotuksetCount.TYOMAHDOLLISUUS + ehdotuksetCount.KOULUTUSMAHDOLLISUUS });
break;
}
},
}),
{
Expand All @@ -290,26 +334,32 @@ export const useToolStore = create<ToolState>()(
),
);

async function fetchKoulutusMahdollisuudet(ids: string[], newPage: number, pageSize: number) {
const { data: koulutusmahdollisuudet } = await client.GET('/api/koulutusmahdollisuudet', {
params: {
query: {
id: paginate(ids, newPage, pageSize),
},
},
});
async function fetchKoulutusMahdollisuudet(ids: string[]) {
const { data: koulutusmahdollisuudet } =
ids.length > 0
? await client.GET('/api/koulutusmahdollisuudet', {
params: {
query: {
id: ids,
},
},
})
: { data: undefined };

return { koulutusmahdollisuusResults: koulutusmahdollisuudet?.sisalto ?? [] };
}

async function fetchTyomahdollisuudet(ids: string[], newPage: number, pageSize: number) {
const { data: tyomahdollisuudet } = await client.GET('/api/tyomahdollisuudet', {
params: {
query: {
id: paginate(ids, newPage, pageSize),
},
},
});
async function fetchTyomahdollisuudet(ids: string[]) {
const { data: tyomahdollisuudet } =
ids.length > 0
? await client.GET('/api/tyomahdollisuudet', {
params: {
query: {
id: ids,
},
},
})
: { data: undefined };

return { tyomahdollisuusResults: tyomahdollisuudet?.sisalto ?? [] };
}

0 comments on commit b9ac18f

Please sign in to comment.