prototype mostly finished

This commit is contained in:
2025-02-08 01:39:47 +01:00
parent 7c36f87149
commit 4757c3e0a9
15 changed files with 418 additions and 118 deletions
+116
View File
@@ -0,0 +1,116 @@
import { useEffect, useState } from 'preact/hooks'
import { Funnel } from '@phosphor-icons/react'
import { marked } from 'marked'
import type { Database } from '@/data/domande-esami.yaml'
const useRemoteValue = <T,>(url: string): T | null => {
const [value, setValue] = useState<T | null>(null)
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(value => setValue(value))
}, [url])
return value
}
type Props = {
course: string
}
export const DomandeEsamiCourse = ({ course }: Props) => {
const database = useRemoteValue<Database>(`/domande-esami/api/${course}.json`)
if (!database) {
return <>Loading...</>
}
// @ts-ignore
requestIdleCallback(() => window.renderMath())
console.log(database)
const courseTags = [
...new Set(
database.questions
.filter(question => question.course === course)
.flatMap(question => question.tags)
),
]
const [selectedTags, setSelectedTags] = useState<string[]>([])
const filteredQuestions = database.questions
.filter(question => question.course === course)
.filter(
question => selectedTags.length === 0 || selectedTags.every(tag => question.tags.includes(tag))
)
return (
<>
<div class="grid-center">
<h3>
<a href="/domande-esami">Domande Esami</a>
</h3>
<h1>{database.names[course]}</h1>
</div>
<div class="card filter">
<div class="grid-h">
<Funnel />
<strong>Filtra Tag</strong>
</div>
<div class="flex-row-wrap">
{selectedTags.length === 0
? courseTags.map(tag => (
<div class="chip clickable" onClick={() => setSelectedTags([tag])}>
{tag}
</div>
))
: courseTags.map(tag => (
<div
class={
selectedTags.includes(tag)
? 'chip clickable'
: 'chip clickable disabled'
}
onClick={() =>
setSelectedTags(
selectedTags.includes(tag)
? selectedTags.filter(t => t !== tag)
: [...selectedTags, tag]
)
}
>
{tag}
</div>
))}
</div>
</div>
<div class="wide-card-list" id="questions">
{filteredQuestions.length === 0 ? (
<div class="grid-center">
<em>No questions found</em>
</div>
) : (
filteredQuestions.map(question => (
<div class="card">
<div
class="text"
dangerouslySetInnerHTML={{
__html: marked(question.content, { async: false }),
}}
/>
<div class="metadata">
{question.tags.map(tag => (
<div class="chip small">{tag}</div>
))}
</div>
</div>
))
)}
</div>
</>
)
}