qmining-page/src/pages/allQuestions.jsx
2023-03-09 16:47:17 +01:00

365 lines
9.6 KiB
JavaScript

import React, { useState, useEffect } from 'react'
import Header from '../components/header'
import LoadingIndicator from '../components/LoadingIndicator'
import QuestionSearchResult from '../components/QuestionSearchResult'
import Subject from '../components/Subject'
import SubjectSelector from '../components/SubjectSelector'
import ExternalLinkIcon from '../components/externalLinkIcon'
import SearchBar from '../components/searchBar'
import styles from './allQuestions.module.css'
import constants from '../constants.json'
const countReducer = (acc, subj) => {
return acc + subj.Questions.length
}
function mergeData(data) {
return data.reduce((acc, db) => {
return [
...acc,
...db.data.map((subj) => {
return {
...subj,
Name: `${subj.Name} [ DB: ${db.dbName} ]`,
}
}),
]
}, [])
}
function fetchData(db) {
return new Promise((resolve) => {
fetch(`${constants.apiUrl}${db.path}`, {
credentials: 'include',
})
.then((resp) => {
return respon()
})
.then((resp) => {
resolve({
dbName: db.name,
data: resp,
})
})
})
}
function fetchAllData(dbs) {
const promises = dbs.map((db) => {
return fetchData(db)
})
return Promise.all(promises)
}
function fetchDbs() {
return new Promise((resolve) => {
fetch(`${constants.apiUrl}getDbs`, {
credentials: 'include',
})
.then((resp) => {
return respon()
})
.then((data) => {
resolve(data)
})
})
}
export default function AllQuestions({ router, globalState, setGlobalState }) {
const [subjectsShowing, setSubjectsShowing] = useState(false)
const [searchTerm, setSearchTerm] = useState('')
const [activeSubjName, setActiveSubjName] = useState('')
const [dbs, setDbs] = useState(null)
const [selectedDb, setSelectedDb] = useState(-1)
const [data, setData] = useState(null)
const [fetchingData, setFetchingData] = useState(false)
const subjectCount = data ? data.length : 0
const questionCount = data ? data.reduce(countReducer, 0) : 0
useEffect(() => {
router.replace(`${router.asPath.replace('.html', '')}`, undefined, {
shallow: true,
})
if (globalState.qdbs) {
setDbs(globalState.qdbs)
} else {
fetchDbs().then((res) => {
setDbs(res)
setGlobalState({
qdbs: res,
})
})
}
}, [])
useEffect(() => {
const db = router.query.db ? decodeURIComponent(router.query.db) : ''
if (db) {
setSelectedDb(db)
}
}, [router.query.db])
useEffect(() => {
const querySearch = router.query.question
? decodeURIComponent(router.query.question)
: ''
if (querySearch) {
setSearchTerm(querySearch)
}
}, [router.query.question])
useEffect(() => {
if (dbs && selectedDb && (selectedDb === 'all' || dbs[selectedDb])) {
if (selectedDb === 'all') {
const hasAll =
globalState.dbs &&
dbs.every((db) => {
return (
Object.keys(globalState.dbs).findIndex((key) => {
return db.name === key
}) !== -1
)
})
if (hasAll) {
const asd = Object.keys(globalState.dbs).map((key) => {
return {
dbName: key,
data: globalState.dbs[key],
}
})
setData(mergeData(asd))
setFetchingData(false)
} else {
fetchAllData(dbs).then((res) => {
setData(mergeData(res))
setFetchingData(false)
let cacheRes = {}
res.forEach((db) => {
cacheRes = {
...cacheRes,
[db.dbName]: db.data,
}
})
setGlobalState({
dbs: cacheRes,
})
})
}
} else {
const selected = dbs[selectedDb]
if (globalState.dbs && globalState.dbs[selected.name]) {
setData(globalState.dbs[selected.name])
setFetchingData(false)
} else {
fetchData(dbs[selectedDb]).then((res) => {
setData(res.data)
setFetchingData(false)
setGlobalState({
dbs: {
...globalState.dbs,
[res.dbName]: res.data,
},
})
})
}
}
}
}, [selectedDb, dbs])
const renderDbSelector = () => {
if (dbs) {
return (
<>
<div className={'pageHeader'}>
<h1>Kérdések és tárgyak</h1>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div className={'description'}>
Ezen az oldalon tudsz manuálisan keresni a kérdések és a tárgyak
között, vagy ellenőrizni, hogy egy adott tárgy szerepel-e a
kérdés- és tárgyadatbázisban. Ezen kívül a kérdéseket le is
töltheted offline használatra. (txt formátumban)
</div>
<div className={'buttonContainer'}>
<div
onClick={() => {
window.open(`${constants.siteUrl}dataeditor`, '_blank')
}}
>
Kérdés szerkesztő
<ExternalLinkIcon size={15} />
</div>
</div>
</div>
<div className={'selectContainer'}>
<select
value={selectedDb}
onChange={(event) => {
const key = event.target.value
setData(null)
setSelectedDb(key)
if (parseInt(key) === -1) {
router.replace(
`${router.pathname}?question=${encodeURIComponent(
searchTerm
)}`,
undefined,
{ shallow: true }
)
return
}
setFetchingData(true)
router.replace(
`${router.pathname}?question=${encodeURIComponent(
searchTerm
)}&db=${key}`,
undefined,
{ shallow: true }
)
}}
>
<option value={-1}>{' Válassz egy adatbázist!'}</option>
{dbs.map((db, i) => {
return (
<option value={i} key={db.path}>
{db.name}
</option>
)
})}
<option value={'all'} key={'all'}>
{'Összes kérdés'}
</option>
</select>
</div>
</>
)
} else {
return null
}
}
const renderSubjectBrowser = () => {
let currSubj = data
? data.find((subj) => {
return subj.Name === activeSubjName
})
: {}
return (
<div>
{data ? (
<>
<SearchBar
searchTerm={searchTerm}
onChange={(e) => {
setSearchTerm(e)
}}
/>
<hr />
<SubjectSelector
data={data}
activeSubjName={activeSubjName}
searchTerm={searchTerm}
onSubjSelect={(subjName) => {
setActiveSubjName(subjName)
}}
/>
<div>
<hr />
<Subject subj={currSubj} />
</div>
</>
) : null}
</div>
)
}
const renderQuestionBrowser = () => {
return (
<div>
{data ? (
<>
<SearchBar
searchTerm={searchTerm}
onChange={(e) => {
setSearchTerm(e)
}}
/>
<div>
<QuestionSearchResult data={data} searchTerm={searchTerm} />
</div>
</>
) : null}
</div>
)
}
return (
<div>
<Header title={'Kérdések és tárgyak'} />
{dbs ? <>{renderDbSelector()}</> : <LoadingIndicator />}
{dbs && data ? (
<>
<div className={styles.info}>
{`Összesen ${questionCount.toLocaleString()} kérdés, ${subjectCount} tárgyból`}
</div>
<div className={'buttonContainer'}>
<div
className={!subjectsShowing ? 'activeButton' : ''}
onClick={() => setSubjectsShowing(false)}
>
Kérdések
</div>
<div
className={subjectsShowing ? 'activeButton' : ''}
onClick={() => setSubjectsShowing(true)}
>
Tárgyak
</div>
<a
onClick={() => {
if (selectedDb === 'all') {
window.open(`${constants.apiUrl}allqr.txt`, '_blank')
} else {
window.open(
`${constants.apiUrl}allqr.txt?db=${dbs[selectedDb].name}`,
'_blank'
)
}
}}
>
{'Kérdések letöltése'}
<ExternalLinkIcon size={15} />
</a>
</div>
{fetchingData ? (
<LoadingIndicator />
) : (
<div>
{subjectsShowing
? renderSubjectBrowser()
: renderQuestionBrowser()}
</div>
)}
</>
) : fetchingData ? (
<div>
Kérdések betöltése, nagy adatbázisoknál ez sokáig tarthat ...
<LoadingIndicator />
</div>
) : null}
</div>
)
}