\n \n {\n favorites && favorites.includes(title)\n ? removeFromFavorites(title)\n : addToFavorites(title);\n }}\n tabIndex={0}\n isCheckbox\n />\n | \n toggleRow(title)}\n >\n {spotlight && }\n {title}\n | \n toggleRow(title)}>{organisation} | \n toggleRow(title)}>{type?.join(\", \")} | \n toggleRow(title)}>{target_audience?.join(\", \")} | \n toggleRow(title)}>\n {description && (\n \n )}\n | \n
\n {expandedRowTitle === title && description && (\n = ({\n row: {\n title,\n themes,\n difficulty,\n goals,\n learning_areas,\n key_competencies,\n description,\n cta_link,\n spotlight,\n },\n rowIndex,\n expandedRowTitle,\n toggleRow,\n favorites,\n addToFavorites,\n removeFromFavorites,\n}) => {\n return (\n <>\n \n \n {\n favorites && favorites.includes(title)\n ? removeFromFavorites(title)\n : addToFavorites(title);\n }}\n tabIndex={0}\n />\n | \n toggleRow(title)}\n >\n {spotlight && }\n {title}\n | \n toggleRow(title)}>{themes?.join(\", \")} | \n toggleRow(title)}>{renderDifficulty(difficulty)} | \n toggleRow(title)}>\n {description && (\n \n )}\n | \n
\n {expandedRowTitle === title && description && (\n \n \n \n \n {description}\n\n \n \n \n \n \n \n \n Doel\n \n {goals?.join(\", \")}\n \n \n\n \n \n \n \n \n \n Leergebied\n \n {learning_areas?.join(\", \")}\n \n \n \n \n \n \n \n \n Sleutelcompetentie\n \n {key_competencies?.join(\", \")}\n \n \n \n\n \n {cta_link && (\n \n \n \n \n \n \n \n \n \n Doel\n \n {goals?.join(\", \")}\n \n \n\n \n \n \n \n \n \n Leergebied\n \n {learning_areas?.join(\", \")}\n \n \n \n \n \n \n \n \n Sleutelcompetentie\n \n {key_competencies?.join(\", \")}\n \n \n \n \n | \n
\n )}\n >\n );\n};\n","import { Message } from \"components/message/Message\";\nimport { FC, useState } from \"react\";\nimport { i18nService } from \"services\";\nimport { InclusionTableRow } from \"./InclusionTableRow\";\nimport { IInclusionRow } from \"./TableWrapper\";\nimport { TABLE_TYPES } from \"../tableTypes\";\nimport { ITussendoortjesRow } from \"components/tussendoortjes/types\";\nimport { TussendoortjesTableRow } from \"components/tussendoortjes/components/TussendoortjesTableRow\";\n\ninterface Props {\n filteredRows: (IInclusionRow | ITussendoortjesRow)[];\n sortColumn?: string | null;\n sortDirection?: string | null;\n handleSort: (column: string, direction: string) => void;\n favorites?: string[];\n addToFavorites: (t: string) => void;\n removeFromFavorites: (t: string) => void;\n tableHeaders: { [key: string]: string };\n tableType: string;\n}\n\nexport const TableContent: FC = ({\n filteredRows,\n sortColumn,\n sortDirection,\n handleSort,\n favorites,\n addToFavorites,\n removeFromFavorites,\n tableHeaders,\n tableType,\n}) => {\n const [expandedRowTitle, setExpandedRowTitle] = useState(null);\n\n const toggleRow = (title: string) =>\n setExpandedRowTitle(title === expandedRowTitle ? null : title);\n\n return (\n <>\n {filteredRows.length > 0 ? (\n \n \n \n | \n {Object.keys(tableHeaders).map((key) => (\n \n \n \n \n | \n ))}\n
\n \n \n {filteredRows.map((row, rowIndex) => {\n switch (tableType) {\n case TABLE_TYPES.INCLUSION:\n return (\n \n );\n case TABLE_TYPES.TUSSENDOORTJES:\n return (\n \n );\n default:\n return null;\n }\n })}\n \n
\n ) : (\n {i18nService.copy[\"siteSearch.noResults\"]}\n )}\n >\n );\n};\n","import { Cube, Tag, User } from \"assets/icons\";\nimport { SelectField } from \"components/form/fields\";\nimport { FC } from \"react\";\nimport { IFieldType, IOption } from \"types\";\n\ninterface Props {\n themaOptions: IOption[];\n targetAudienceOptions: IOption[];\n materialOptions: IOption[];\n setThema: (thema: string | null) => void;\n setTargetAudience: (targetAudience: string | null) => void;\n setMaterial: (thema: string | null) => void;\n}\n\nexport const TableFilters: FC = ({\n themaOptions = [],\n targetAudienceOptions = [],\n materialOptions = [],\n setThema,\n setTargetAudience,\n setMaterial,\n}) => {\n return (\n \n }\n name=\"Thema\"\n label=\"Thema\"\n onChange={({ currentTarget: { value } }) => setThema(value)}\n />\n }\n name=\"Doelgroep\"\n label=\"Doelgroep\"\n onChange={({ currentTarget: { value } }) => setTargetAudience(value)}\n />\n }\n name=\"Materiaal\"\n label=\"Materiaal\"\n onChange={({ currentTarget: { value } }) => setMaterial(value)}\n />\n
\n );\n};\n","import { SearchField } from \"components/search/components\";\nimport { FC } from \"react\";\n\ninterface Props {\n setSearch?: ({ search }: { search: string }) => void;\n}\n\nexport const TableSearch: FC = ({ setSearch }) => {\n return ;\n};\n","import { FC } from \"react\";\nimport { useTableSearch } from \"../useTableSearch\";\nimport { TableContent } from \"./TableContent\";\nimport { TableFilters } from \"./TableFilters\";\nimport { TableSearch } from \"./TableSearch\";\nimport { TABLE_TYPES } from \"../tableTypes\";\n\nexport interface IInclusionRow {\n title: string;\n organisation: string;\n type?: string[];\n cta_attachment?: string[];\n cta_tool?: string;\n description: string;\n image?: string;\n spotlight: boolean;\n target_audience?: string[];\n theme?: string[];\n}\n\ninterface Props {\n rows: IInclusionRow[];\n}\n\nconst tableHeaders: { [key: string]: string } = {\n title: \"Titel\",\n organisation: \"Organisatie\",\n type: \"Type\",\n target_audience: \"Doelgroep\",\n};\n\nexport const TableWrapper: FC = ({ rows }) => {\n const {\n state: {\n sortColumn,\n sortDirection,\n themaOptions,\n targetAudienceOptions,\n materialOptions,\n filteredRows,\n favorites,\n },\n actions: {\n setSearch,\n setThema,\n setTargetAudience,\n setMaterial,\n handleSort,\n addToFavorites,\n removeFromFavorites,\n },\n } = useTableSearch({ rows });\n\n return (\n <>\n \n \n \n >\n );\n};\n","import ReactDOM from \"react-dom\";\nimport { TableWrapper } from \"./components/TableWrapper\";\n\n(() => {\n const containers = document.querySelectorAll(\n \"[data-mediawijs-inclusion]\"\n );\n\n const data = document.getElementById(\"inclusion-data\")?.textContent;\n\n if (!containers || !data) return;\n\n ReactDOM.render(, containers[0]);\n})();\n","import { some, sortBy, uniq, without } from \"lodash-es\";\nimport { useCallback, useMemo, useReducer } from \"react\";\nimport { i18nService } from \"services\";\nimport { IOption } from \"types\";\nimport { ITussendoortjesRow } from \"./types\";\nimport { renderDifficulty } from \"./components/TussendoortjesTableRow\";\n\ninterface IState {\n search?: string;\n thema?: string | null;\n difficulty?: string | null;\n sortColumn?: string | null;\n sortDirection?: string | null;\n favorites?: string[];\n}\n\nconst initialState: IState = {\n search: \"\",\n thema: null,\n difficulty: null,\n sortColumn: \"title\",\n sortDirection: \"asc\",\n favorites: JSON.parse(\n localStorage.getItem(\"favorite-tussendoortjes-rows\") || \"[]\"\n ),\n};\n\nenum Type {\n SET_SEARCH = \"SET_SEARCH\",\n SET_THEMA = \"SET_THEMA\",\n SET_DIFFICULTY = \"SET_DIFFICULTY\",\n SET_SORT_COLUMN = \"SET_SORT_COLUMN\",\n SET_SORT_DIRECTION = \"SET_SORT_DIRECTION\",\n ADD_TO_FAVORITES = \"ADD_TO_FAVORITES\",\n REMOVE_FROM_FAVORITES = \"REMOVE_FROM_FAVORITES\",\n}\n\nexport const useTussendoortjes = ({ rows }: { rows: ITussendoortjesRow[] }) => {\n const [state, dispatch] = useReducer(\n (state: IState, { type, payload }: { type: Type; payload: any }) => {\n switch (type) {\n case Type.SET_SEARCH: {\n return {\n ...state,\n search: payload.search,\n };\n }\n\n case Type.SET_THEMA: {\n return {\n ...state,\n thema: payload.thema,\n };\n }\n\n case Type.SET_DIFFICULTY: {\n return {\n ...state,\n difficulty: payload.difficulty,\n };\n }\n\n case Type.SET_SORT_COLUMN: {\n return {\n ...state,\n sortColumn: payload.sortColumn,\n };\n }\n\n case Type.SET_SORT_DIRECTION: {\n return {\n ...state,\n sortDirection: payload.sortDirection,\n };\n }\n\n case Type.ADD_TO_FAVORITES: {\n localStorage.setItem(\n \"favorite-tussendoortjes-rows\",\n JSON.stringify([\n ...JSON.parse(\n localStorage.getItem(\"favorite-tussendoortjes-rows\") || \"[]\"\n ),\n payload.favorite,\n ])\n );\n return {\n ...state,\n ...(state.favorites && {\n favorites: [...state.favorites, payload.favorite],\n }),\n };\n }\n\n case Type.REMOVE_FROM_FAVORITES: {\n localStorage.setItem(\n \"favorite-tussendoortjes-rows\",\n JSON.stringify(\n without(\n JSON.parse(\n localStorage.getItem(\"favorite-tussendoortjes-rows\") || \"[]\"\n ),\n payload.favorite\n )\n )\n );\n return {\n ...state,\n ...(state.favorites && {\n favorites: without(state.favorites, payload.favorite),\n }),\n };\n }\n\n default: {\n return state;\n }\n }\n },\n initialState\n );\n\n const setSearch = ({ search }: { search: string }) => {\n dispatch({\n type: Type.SET_SEARCH,\n payload: {\n search,\n },\n });\n };\n\n const setThema = (thema: string | null) => {\n dispatch({\n type: Type.SET_THEMA,\n payload: {\n thema,\n },\n });\n };\n\n const setDifficulty = (difficulty: string | null) => {\n dispatch({\n type: Type.SET_DIFFICULTY,\n payload: {\n difficulty,\n },\n });\n };\n\n const themaOptions = useMemo(\n () => [\n {\n label: i18nService.copy[\"toolQuickSearch.choose\"]?.replace(\n \"@filter\",\n \"thema\"\n ),\n value: \"\",\n type: \"\",\n name: \"\",\n },\n ...sortBy(\n uniq(\n rows\n .map(({ themes }) => themes)\n .flat()\n .filter((theme) => !!theme)\n ).map((theme: any) => ({\n label: theme,\n value: theme,\n name: theme,\n type: theme,\n })),\n \"label\"\n ),\n ],\n [rows]\n );\n\n const difficultyOptions = useMemo(\n () => [\n {\n label: i18nService.copy[\"toolQuickSearch.choose\"]?.replace(\n \"@filter\",\n \"moeilijkheidsgraad\"\n ),\n value: \"\",\n type: \"\",\n name: \"\",\n },\n ...sortBy(\n uniq(\n rows\n .map(({ difficulty }) => difficulty)\n .filter((type) => !!type)\n .flat()\n ).map((type: any) => ({\n label: renderDifficulty(type),\n value: type,\n name: type,\n type,\n })),\n \"label\"\n ),\n ],\n [rows]\n );\n\n const filteredRows = useMemo(() => {\n const filtered = rows.filter(\n ({\n title,\n description,\n themes,\n difficulty,\n goals,\n key_competencies,\n learning_areas,\n }) => {\n // If any field is not filled in, don't show the row.\n\n const match = (t: string, target?: string | null) =>\n !target || t.toLowerCase().includes(target.toLowerCase());\n\n const matchesSearch =\n match(title, state.search) ||\n (description && match(description, state.search));\n\n const matchesTheme = some(themes, (t: string) => match(t, state.thema));\n\n const matchesDifficulty = match(\n difficulty.toString(),\n state.difficulty\n );\n\n return matchesSearch && matchesTheme && matchesDifficulty;\n }\n );\n\n if (state.sortColumn === null || state.sortColumn === undefined)\n return filtered.sort((a, b) => {\n let aIsFavorite = state.favorites?.includes(a.title);\n let bIsFavorite = state.favorites?.includes(b.title);\n\n // If either A or B is a favorite, prioritize it\n if (aIsFavorite || bIsFavorite) {\n if (aIsFavorite && !bIsFavorite) {\n return -1;\n }\n if (!aIsFavorite && bIsFavorite) {\n return 1;\n }\n }\n\n // If either A or B is spotlight, prioritize it\n if (a.spotlight || b.spotlight) {\n if (a.spotlight && !b.spotlight) {\n return -1;\n }\n if (!a.spotlight && b.spotlight) {\n return 1;\n }\n }\n\n return 0;\n });\n\n return filtered.sort((a, b) => {\n //@ts-ignore\n let compareValueA = a[state.sortColumn].toString().trim();\n //@ts-ignore\n let compareValueB = b[state.sortColumn].toString().trim();\n\n if (state.sortColumn === \"difficulty\") {\n //@ts-ignore\n compareValueA = renderDifficulty(parseInt(a[state.sortColumn]));\n //@ts-ignore\n compareValueB = renderDifficulty(b[state.sortColumn]);\n }\n\n let aIsFavorite = state.favorites?.includes(a.title);\n let bIsFavorite = state.favorites?.includes(b.title);\n\n // If either A or B is a favorite, prioritize it\n if (aIsFavorite || bIsFavorite) {\n if (aIsFavorite && !bIsFavorite) {\n return -1;\n }\n if (!aIsFavorite && bIsFavorite) {\n return 1;\n }\n }\n\n // If either A or B is spotlight, prioritize it\n if (a.spotlight || b.spotlight) {\n if (a.spotlight && !b.spotlight) {\n return -1;\n }\n if (!a.spotlight && b.spotlight) {\n return 1;\n }\n }\n\n // If A and B are both favorites, or neither is a favorite, sort alphabetically\n if (typeof compareValueA === \"string\") {\n compareValueA = compareValueA.toLowerCase();\n compareValueB = compareValueB.toLowerCase();\n } else {\n compareValueA = compareValueA.map((val: string) => val.toLowerCase());\n compareValueB = compareValueB.map((val: string) => val.toLowerCase());\n }\n\n return state.sortDirection === \"asc\"\n ? compareValueA < compareValueB\n ? -1\n : 1\n : compareValueA > compareValueB\n ? -1\n : 1;\n });\n // eslint-disable-next-line\n }, [\n rows,\n state.difficulty,\n state.search,\n state.sortColumn,\n state.sortDirection,\n state.thema,\n ]);\n\n const handleSort = useCallback(\n (column: string) => {\n if (state.sortColumn === column) {\n if (state.sortDirection === \"desc\") {\n dispatch({\n type: Type.SET_SORT_COLUMN,\n payload: {\n sortColumn: null,\n },\n });\n } else {\n dispatch({\n type: Type.SET_SORT_DIRECTION,\n payload: {\n sortDirection: \"desc\",\n },\n });\n }\n } else {\n dispatch({\n type: Type.SET_SORT_COLUMN,\n payload: {\n sortColumn: column,\n },\n });\n\n dispatch({\n type: Type.SET_SORT_DIRECTION,\n payload: {\n sortDirection: \"asc\",\n },\n });\n }\n },\n [state.sortColumn, state.sortDirection]\n );\n\n const addToFavorites = (favorite: string) => {\n dispatch({\n type: Type.ADD_TO_FAVORITES,\n payload: {\n favorite,\n },\n });\n };\n\n const removeFromFavorites = (favorite: string) => {\n dispatch({\n type: Type.REMOVE_FROM_FAVORITES,\n payload: {\n favorite,\n },\n });\n };\n\n return {\n state: {\n sortColumn: state.sortColumn,\n sortDirection: state.sortDirection,\n favorites: state.favorites,\n themaOptions,\n difficultyOptions,\n filteredRows,\n },\n actions: {\n setSearch,\n setThema,\n setDifficulty,\n handleSort,\n addToFavorites,\n removeFromFavorites,\n },\n };\n};\n","import { BarChart, Tag } from \"assets/icons\";\nimport { SelectField } from \"components/form/fields\";\nimport { FC } from \"react\";\nimport { IFieldType, IOption } from \"types\";\n\ninterface Props {\n themaOptions: IOption[];\n difficultyOptions: IOption[];\n setThema: (thema: string | null) => void;\n setDifficulty: (difficulty: string | null) => void;\n}\n\nexport const TableFilters: FC = ({\n themaOptions = [],\n difficultyOptions = [],\n setThema,\n setDifficulty,\n}) => {\n return (\n \n }\n name=\"Thema\"\n label=\"Thema\"\n className=\"table-overview-filters__thema\"\n onChange={({ currentTarget: { value } }) => setThema(value)}\n />\n }\n name=\"Moeilijkheidsgraad\"\n label=\"Moeilijkheidsgraad\"\n className=\"table-overview-filters__difficulty\"\n onChange={({ currentTarget: { value } }) => setDifficulty(value)}\n />\n
\n );\n};\n","import { FC } from \"react\";\nimport { useTussendoortjes } from \"../useTussendoortjes\";\nimport { ITussendoortjesRow } from \"../types\";\nimport { TABLE_TYPES } from \"components/inclusion/tableTypes\";\nimport { TableFilters } from \"./TableFIlters\";\nimport { TableSearch } from \"components/inclusion/components/TableSearch\";\nimport { TableContent } from \"components/inclusion/components/TableContent\";\n\ninterface Props {\n rows: ITussendoortjesRow[];\n}\n\nconst tableHeaders: { [key: string]: string } = {\n title: \"Titel\",\n themes: \"Thema\",\n difficulty: \"Moeilijkheidsgraad\",\n};\n\nexport const TableWrapper: FC = ({ rows }) => {\n const {\n state: {\n sortColumn,\n sortDirection,\n filteredRows,\n themaOptions,\n favorites,\n difficultyOptions,\n },\n actions: {\n setSearch,\n setThema,\n handleSort,\n addToFavorites,\n removeFromFavorites,\n setDifficulty,\n },\n } = useTussendoortjes({ rows });\n\n return (\n <>\n \n \n \n >\n );\n};\n","import ReactDOM from \"react-dom\";\nimport { TableWrapper } from \"./components/TableWrapper\";\n\n(() => {\n const containers = document.querySelectorAll(\n \"[data-mediawijs-tussendoortjes]\"\n );\n\n const data = document.getElementById(\"tussendoortjes-data\")?.textContent;\n\n if (!containers || !data) return;\n\n ReactDOM.render(, containers[0]);\n})();\n","import React, { useState } from \"react\";\n\nimport { urlService } from \"services\";\nimport { ActiveToolboxFacetType, IToolboxFacet } from \"types\";\nimport { useOnPersistedPageShow } from \"utils\";\n\nimport { ToolboxQuickSearchForm } from \"../components\";\n\ninterface ToolboxSearchAppProps {\n facets: IToolboxFacet[];\n}\n\nexport const ToolboxQuickSearchContainer: React.FC = ({\n facets,\n}) => {\n const [isLoading, setLoading] = useState(false);\n\n // bfcache fix\n useOnPersistedPageShow(() => setLoading(false));\n\n const handleSubmit = (data: ActiveToolboxFacetType) => {\n setLoading(true);\n\n // redirect to toolbox search single with chosen facets\n window.location.href = urlService.generateToolboxSearchUrl(data);\n };\n return (\n \n \n
\n );\n};\n","import ReactDOM from \"react-dom\";\n\nimport { IToolboxFacet } from \"types\";\n\nimport { ToolboxQuickSearchContainer } from \"./containers\";\nimport { BrowserRouter } from \"react-router-dom\";\n\n(() => {\n const toolboxQuickSearchContainers = document.querySelectorAll(\n \"[data-toolbox-quick-search]\"\n );\n\n if (!toolboxQuickSearchContainers) return;\n\n toolboxQuickSearchContainers.forEach((toolboxQuickSearchContainer) => {\n const data = toolboxQuickSearchContainer.dataset.toolboxQuickSearch;\n // toolboxQuickSearchContainer.dataset.toolboxQuickSearch = \"\"; //cleanup\n\n if (!data) return;\n\n const toolboxQuickSearchData = JSON.parse(data) as IToolboxFacet[];\n\n ReactDOM.render(\n \n \n ,\n toolboxQuickSearchContainer\n );\n });\n})();\n","import \"sanitize.css\";\n\nimport \"./index.scss\";\n\nimport \"elements/scripts\";\nimport \"components/scripts\";\n\nimport { loggerService, lazyLoadService } from \"services\";\nimport { openMenu } from \"components/header\";\n\nloggerService.log({\n icon: \"👾\",\n title: \"Test\",\n body: \"Test\",\n});\n\n// init lazy load script\nlazyLoadService.observe();\n\n// used on 403/404 pages to open the menu from a text link\n(() => {\n const menuOpenLinks = document.querySelectorAll(\n \"[data-menu-open-link]\"\n );\n\n menuOpenLinks.forEach((link) => {\n link.addEventListener(\"click\", () => {\n openMenu();\n });\n });\n})();\n"],"sourceRoot":""}