2023-05-05 19:56:51 +02:00
|
|
|
// Dependencies
|
|
|
|
import orderBy from 'lodash.orderby'
|
2023-05-19 08:34:08 +02:00
|
|
|
import { measurements } from 'shared/prebuild/data/design-measurements.mjs'
|
2023-05-08 19:28:03 +02:00
|
|
|
import { siteConfig } from 'site/site.config.mjs'
|
|
|
|
import { capitalize } from 'shared/utils.mjs'
|
2023-05-05 19:56:51 +02:00
|
|
|
// Hooks
|
|
|
|
import { useState, useEffect } from 'react'
|
|
|
|
import { useTranslation } from 'next-i18next'
|
|
|
|
import { useAccount } from 'shared/hooks/use-account.mjs'
|
|
|
|
import { useBackend } from 'shared/hooks/use-backend.mjs'
|
|
|
|
// Components
|
|
|
|
import { SetCandidate, ns as setNs } from 'shared/components/sets/set-candidate.mjs'
|
2023-07-26 20:05:16 +02:00
|
|
|
import { PopoutWrapper } from 'shared/components/wrappers/popout.mjs'
|
2023-05-08 19:28:03 +02:00
|
|
|
import { Tag } from 'shared/components/tag.mjs'
|
|
|
|
import { FilterIcon } from 'shared/components/icons.mjs'
|
2023-05-05 19:56:51 +02:00
|
|
|
|
|
|
|
export const ns = setNs
|
|
|
|
|
2023-06-20 20:19:31 +02:00
|
|
|
export const CuratedSetPicker = ({ design, language, href, clickHandler }) => {
|
2023-05-08 09:31:37 +02:00
|
|
|
// Hooks
|
2023-05-19 16:31:28 +02:00
|
|
|
const { token } = useAccount()
|
2023-05-08 09:31:37 +02:00
|
|
|
const backend = useBackend(token)
|
2023-06-21 11:09:57 -05:00
|
|
|
const { t, i18n } = useTranslation('sets')
|
2023-05-08 09:31:37 +02:00
|
|
|
|
|
|
|
// State
|
2023-05-08 19:28:03 +02:00
|
|
|
const [curatedSets, setCuratedSets] = useState([])
|
|
|
|
const [filter, setFilter] = useState([])
|
|
|
|
const [tags, setTags] = useState([])
|
|
|
|
|
2023-05-08 09:31:37 +02:00
|
|
|
// Effects
|
|
|
|
useEffect(() => {
|
|
|
|
const getCuratedSets = async () => {
|
|
|
|
const result = await backend.getCuratedSets()
|
|
|
|
if (result.success) {
|
2023-05-08 19:28:03 +02:00
|
|
|
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)
|
|
|
|
}
|
2023-05-08 09:31:37 +02:00
|
|
|
setCuratedSets(all)
|
2023-05-08 19:28:03 +02:00
|
|
|
setTags([...allTags])
|
2023-05-08 09:31:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
getCuratedSets()
|
2023-06-22 11:36:46 -05:00
|
|
|
}, [backend, language])
|
2023-05-08 19:28:03 +02:00
|
|
|
|
|
|
|
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)}`
|
2023-07-17 11:40:45 -05:00
|
|
|
if (set[key]) setTags.push(...set[key])
|
2023-05-08 19:28:03 +02:00
|
|
|
}
|
|
|
|
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()
|
2023-05-08 09:31:37 +02:00
|
|
|
|
|
|
|
// Need to sort designs by their translated title
|
|
|
|
const translated = {}
|
|
|
|
for (const d of list) translated[t(`${d}.t`)] = d
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2023-05-08 19:28:03 +02:00
|
|
|
<h3>{t('curatedSets')}</h3>
|
|
|
|
{tags.map((tag) => (
|
2023-05-19 18:27:36 +02:00
|
|
|
<Tag onClick={() => addFilter(tag)} tag={tag} key={tag}>
|
2023-05-19 18:15:06 +02:00
|
|
|
{tag}
|
|
|
|
</Tag>
|
2023-05-08 19:28:03 +02:00
|
|
|
))}
|
|
|
|
<div className="my-2 p-2 px-4 border rounded-lg bg-secondary bg-opacity-10 max-w-xl">
|
|
|
|
<div className="flex flex-row items-center justify-between gap-2">
|
|
|
|
<FilterIcon className="w-6 h-6 text-secondary" />
|
|
|
|
<span>
|
|
|
|
{list.length} / {curatedSets.length}
|
|
|
|
</span>
|
|
|
|
<button onClick={() => setFilter([])} className="btn btn-secondary btn-sm">
|
|
|
|
clear
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
{filter.map((tag) => (
|
2023-05-19 16:31:28 +02:00
|
|
|
<Tag onClick={() => removeFilter(tag)} color="success" hoverColor="error" key={tag}>
|
2023-05-08 19:28:03 +02:00
|
|
|
{tag}
|
|
|
|
</Tag>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
<div className="flex flex-row flex-wrap gap-2">
|
|
|
|
{orderBy(list, ['name'], ['asc']).map((set) => (
|
2023-05-19 16:31:28 +02:00
|
|
|
<div className="w-full lg:w-96" key={set.id}>
|
2023-06-21 11:09:57 -05:00
|
|
|
<SetCandidate
|
2023-05-08 19:28:03 +02:00
|
|
|
requiredMeasies={measurements[design]}
|
2023-06-21 11:09:57 -05:00
|
|
|
{...{ set, design, href, clickHandler, language: i18n.language }}
|
2023-05-08 19:28:03 +02:00
|
|
|
/>
|
2023-05-08 09:31:37 +02:00
|
|
|
</div>
|
2023-05-08 19:28:03 +02:00
|
|
|
))}
|
|
|
|
</div>
|
2023-05-08 09:31:37 +02:00
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-06-21 12:29:19 +02:00
|
|
|
export const UserSetPicker = ({ design, t, href, clickHandler }) => {
|
2023-05-05 19:56:51 +02:00
|
|
|
// Hooks
|
2023-05-19 16:31:28 +02:00
|
|
|
const { token } = useAccount()
|
2023-05-05 19:56:51 +02:00
|
|
|
const backend = useBackend(token)
|
|
|
|
|
|
|
|
// State
|
|
|
|
const [sets, setSets] = useState({})
|
|
|
|
|
|
|
|
// Effects
|
|
|
|
useEffect(() => {
|
|
|
|
const getSets = async () => {
|
|
|
|
const result = await backend.getSets()
|
|
|
|
if (result.success) {
|
|
|
|
const all = {}
|
|
|
|
for (const set of result.data.sets) all[set.id] = set
|
|
|
|
setSets(all)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
getSets()
|
2023-07-06 07:26:39 -05:00
|
|
|
}, [backend])
|
2023-05-05 19:56:51 +02:00
|
|
|
|
2023-05-08 19:28:03 +02:00
|
|
|
return Object.keys(sets).length < 1 ? (
|
2023-06-21 11:09:57 -05:00
|
|
|
<PopoutWrapper tip noP>
|
2023-05-08 19:28:03 +02:00
|
|
|
<h5>{t('patternForWhichSet')}</h5>
|
|
|
|
<p>{t('fsmtm')}</p>
|
|
|
|
</PopoutWrapper>
|
|
|
|
) : (
|
2023-05-05 19:56:51 +02:00
|
|
|
<>
|
2023-05-08 19:28:03 +02:00
|
|
|
<h3>{t('yourSets')}</h3>
|
2023-05-05 19:56:51 +02:00
|
|
|
{Object.keys(sets).length > 0 ? (
|
2023-05-08 09:31:37 +02:00
|
|
|
<>
|
|
|
|
<div className="flex flex-row flex-wrap gap-2">
|
|
|
|
{orderBy(sets, ['name'], ['asc']).map((set) => (
|
2023-05-19 16:31:28 +02:00
|
|
|
<div className="w-full lg:w-96" key={set.id}>
|
2023-06-20 17:30:18 +02:00
|
|
|
<SetCandidate
|
|
|
|
requiredMeasies={measurements[design]}
|
2023-06-20 20:19:31 +02:00
|
|
|
{...{ set, design, href, clickHandler }}
|
2023-06-20 17:30:18 +02:00
|
|
|
/>
|
2023-05-08 09:31:37 +02:00
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
</>
|
2023-05-05 19:56:51 +02:00
|
|
|
) : (
|
2023-05-08 09:31:37 +02:00
|
|
|
<PopoutWrapper fixme compact>
|
|
|
|
Implement UI for when there are no sets
|
|
|
|
</PopoutWrapper>
|
2023-05-05 19:56:51 +02:00
|
|
|
)}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
2023-05-08 09:31:37 +02:00
|
|
|
|
2023-06-21 12:33:09 +02:00
|
|
|
export const BookmarkedSetPicker = ({ t }) => (
|
2023-05-08 09:31:37 +02:00
|
|
|
<>
|
2023-05-08 19:28:03 +02:00
|
|
|
<h3>{t('bookmarkedSets')}</h3>
|
|
|
|
<PopoutWrapper fixme>Implement bookmarked set picker (also implement bookmarks)</PopoutWrapper>
|
2023-05-08 09:31:37 +02:00
|
|
|
</>
|
|
|
|
)
|
2023-05-08 19:28:03 +02:00
|
|
|
|
2023-06-21 12:33:09 +02:00
|
|
|
export const SetPicker = ({ design, href = false, clickHandler = false }) => {
|
2023-05-08 19:28:03 +02:00
|
|
|
const { t, i18n } = useTranslation('sets')
|
|
|
|
const { language } = i18n
|
|
|
|
|
2023-06-20 20:19:31 +02:00
|
|
|
const pickerProps = { design, t, language, href, clickHandler }
|
2023-05-08 19:28:03 +02:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h2>{t('chooseSet')}</h2>
|
|
|
|
<UserSetPicker {...pickerProps} />
|
2023-06-21 11:09:57 -05:00
|
|
|
<CuratedSetPicker {...pickerProps} />
|
2023-05-08 19:28:03 +02:00
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
2023-06-20 20:19:31 +02:00
|
|
|
|
|
|
|
//<BookmarkedSetPicker {...pickerProps} />
|
|
|
|
//<CuratedSetPicker {...pickerProps} />
|