2023-11-14 15:10:00 +00:00
|
|
|
import { clsx } from 'clsx'
|
2024-06-24 17:50:27 +00:00
|
|
|
import { For, Show, createSignal } from 'solid-js'
|
|
|
|
import type { Topic } from '~/graphql/schema/core.gen'
|
2023-03-23 17:15:50 +00:00
|
|
|
import { useLocalize } from '../../../context/localize'
|
2023-05-10 20:20:53 +00:00
|
|
|
import styles from './TopicSelect.module.scss'
|
2023-03-23 17:15:50 +00:00
|
|
|
|
|
|
|
type TopicSelectProps = {
|
|
|
|
topics: Topic[]
|
2023-03-23 17:47:36 +00:00
|
|
|
selectedTopics: Topic[]
|
2023-03-23 17:15:50 +00:00
|
|
|
onChange: (selectedTopics: Topic[]) => void
|
2023-05-10 20:20:53 +00:00
|
|
|
mainTopic?: Topic
|
|
|
|
onMainTopicChange: (mainTopic: Topic) => void
|
2023-03-23 17:15:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const TopicSelect = (props: TopicSelectProps) => {
|
|
|
|
const { t } = useLocalize()
|
2024-06-24 17:50:27 +00:00
|
|
|
const [isOpen, setIsOpen] = createSignal(false)
|
|
|
|
const [searchTerm, setSearchTerm] = createSignal('')
|
2023-03-23 17:15:50 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const handleChange = (topic: Topic) => {
|
|
|
|
const isSelected = props.selectedTopics.some((selectedTopic) => selectedTopic.slug === topic.slug)
|
|
|
|
let newSelectedTopics: Topic[]
|
2023-05-10 20:20:53 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
if (isSelected) {
|
|
|
|
newSelectedTopics = props.selectedTopics.filter((selectedTopic) => selectedTopic.slug !== topic.slug)
|
|
|
|
} else {
|
|
|
|
newSelectedTopics = [...props.selectedTopics, topic]
|
|
|
|
}
|
2023-03-23 17:15:50 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
props.onChange(newSelectedTopics)
|
2023-03-23 17:15:50 +00:00
|
|
|
}
|
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const handleMainTopicChange = (topic: Topic) => {
|
2023-05-10 20:20:53 +00:00
|
|
|
props.onMainTopicChange(topic)
|
2024-06-24 17:50:27 +00:00
|
|
|
setIsOpen(false)
|
2023-05-10 20:20:53 +00:00
|
|
|
}
|
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const handleSearch = (event: InputEvent) => {
|
|
|
|
setSearchTerm((event.currentTarget as HTMLInputElement).value)
|
|
|
|
}
|
2023-05-10 20:20:53 +00:00
|
|
|
|
2024-06-24 17:50:27 +00:00
|
|
|
const filteredTopics = () => {
|
|
|
|
return props.topics.filter((topic: Topic) =>
|
|
|
|
topic?.title?.toLowerCase().includes(searchTerm().toLowerCase()),
|
2023-05-10 20:20:53 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-03-23 17:47:36 +00:00
|
|
|
return (
|
2024-06-24 17:50:27 +00:00
|
|
|
<div class="TopicSelect">
|
|
|
|
<div class={styles.selectedTopics}>
|
|
|
|
<For each={props.selectedTopics}>
|
|
|
|
{(topic) => (
|
|
|
|
<div
|
|
|
|
class={clsx(styles.selectedTopic, {
|
|
|
|
[styles.mainTopic]: props.mainTopic?.slug === topic.slug,
|
|
|
|
})}
|
|
|
|
onClick={() => handleMainTopicChange(topic)}
|
|
|
|
>
|
|
|
|
{topic.title}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</div>
|
|
|
|
<div class={styles.selectWrapper} onClick={() => setIsOpen(true)}>
|
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
placeholder={t('Topics')}
|
|
|
|
class={styles.searchInput}
|
|
|
|
value={searchTerm()}
|
|
|
|
onInput={handleSearch}
|
|
|
|
/>
|
|
|
|
<Show when={isOpen()}>
|
|
|
|
<div class={styles.options}>
|
|
|
|
<For each={filteredTopics()}>
|
|
|
|
{(topic) => (
|
|
|
|
<div
|
|
|
|
class={clsx(styles.option, {
|
|
|
|
[styles.disabled]: props.selectedTopics.some(
|
|
|
|
(selectedTopic) => selectedTopic.slug === topic.slug,
|
|
|
|
),
|
|
|
|
})}
|
|
|
|
onClick={() => handleChange(topic)}
|
|
|
|
>
|
|
|
|
{topic.title}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</div>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
</div>
|
2023-03-23 17:47:36 +00:00
|
|
|
)
|
2023-03-23 17:15:50 +00:00
|
|
|
}
|