// Dependencies import { capitalize } from 'shared/utils.mjs' import { siteConfig } from 'site/site.config.mjs' // Context import { LoadingContext } from 'shared/context/loading-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs' // Hooks import { useState, useEffect, useContext } from 'react' import { useTranslation } from 'next-i18next' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useToast } from 'shared/hooks/use-toast.mjs' // Components import Link from 'next/link' import { Collapse } from 'shared/components/collapse.mjs' import { TrashIcon, EditIcon, FilterIcon } from 'shared/components/icons.mjs' import { ModalWrapper } from 'shared/components/wrappers/modal.mjs' import Timeago from 'react-timeago' import { Tag } from 'shared/components/tag.mjs' export const ns = ['toast', 'curate', 'sets', 'account'] export const Row = ({ title, children }) => (
{title}
{children}
) const CuratedSet = ({ set, account, t, startLoading, stopLoading, backend, refresh, toast, language, }) => { const { setModal } = useContext(ModalContext) const remove = async () => { startLoading() const result = await backend.removeCuratedMeasurementsSet(set.id) if (result) toast.success(t('gone')) else toast.for.backendError() // This just forces a refresh of the list from the server // We obviously did not add a key here, but rather removed one refresh() stopLoading() } const removeModal = () => { setModal(

{t('curate:areYouCertain')}

{t('curate:deleteCuratedItemWarning')}

) } return ( , , ]} > {set.id} {siteConfig.languages .sort() .map((lang) => capitalize(lang)) .map((lang) => ( {lang} {t('name')} } key={`name${lang}`} > {set[`name${lang}`]} ))} edit ) } export const CurateSets = () => { // Context const { startLoading, stopLoading } = useContext(LoadingContext) // Hooks const { account, token } = useAccount() const backend = useBackend(token) const { t, i18n } = useTranslation('sets', 'curate', 'toast', 'account') const { language } = i18n const toast = useToast() // State const [curatedSets, setCuratedSets] = useState([]) const [filter, setFilter] = useState([]) const [tags, setTags] = useState([]) const [reload, setReload] = useState(0) // Force a refresh const refresh = () => setReload(reload + 1) // Effects useEffect(() => { const getCuratedSets = async () => { const result = await backend.getCuratedSets() if (result.success) { const all = [] const allTags = new Set() for (const set of result.data.curatedSets) { all.push(set) for (const tag of set[`tags${capitalize(language)}`]) allTags.add(tag) } setCuratedSets(all) setTags([...allTags]) } } getCuratedSets() }, [reload]) const addFilter = (tag) => { const newFilter = [...filter, tag] setFilter(newFilter) } const removeFilter = (tag) => { const newFilter = filter.filter((t) => t !== tag) setFilter(newFilter) } const applyFilter = () => { const newList = new Set() for (const set of curatedSets) { const setTags = [] for (const lang of siteConfig.languages) { const key = `tags${capitalize(lang)}` setTags.push(...set[key]) } let match = 0 for (const tag of filter) { if (setTags.includes(tag)) match++ } if (match === filter.length) newList.add(set) } return [...newList] } const list = applyFilter() return (
{tags.map((tag) => ( addFilter(tag)} key={tag}> {tag} ))}
{list.length} / {curatedSets.length}
{filter.map((tag) => ( removeFilter(tag)} color="success" hoverColor="error" key={tag}> {tag} ))} {list.map((set) => ( ))}
) }