mirror of
https://github.com/skidoodle/erettsegi-browser.git
synced 2025-02-15 05:39:15 +01:00
minor changes / cleanup
This commit is contained in:
parent
f1de0d54ac
commit
6275b083db
10 changed files with 2301 additions and 5912 deletions
4035
package-lock.json
generated
4035
package-lock.json
generated
File diff suppressed because it is too large
Load diff
26
package.json
26
package.json
|
@ -10,22 +10,22 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nextui-org/react": "^2.1.13",
|
"@nextui-org/react": "^2.2.9",
|
||||||
"@types/node": "20.8.0",
|
"@types/node": "20.10.4",
|
||||||
"@types/react": "18.2.23",
|
"@types/react": "18.2.43",
|
||||||
"@types/react-dom": "18.2.8",
|
"@types/react-dom": "18.2.17",
|
||||||
"@vercel/analytics": "^1.0.2",
|
"@vercel/analytics": "^1.1.1",
|
||||||
"autoprefixer": "10.4.16",
|
"autoprefixer": "10.4.16",
|
||||||
"eslint": "8.50.0",
|
"eslint": "8.55.0",
|
||||||
"eslint-config-next": "13.5.3",
|
"eslint-config-next": "14.0.4",
|
||||||
"framer-motion": "^10.16.4",
|
"framer-motion": "^10.16.16",
|
||||||
"next": "13.5.3",
|
"next": "14.0.4",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"postcss": "8.4.31",
|
"postcss": "8.4.32",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.12.0",
|
||||||
"tailwindcss": "3.3.3",
|
"tailwindcss": "3.3.6",
|
||||||
"typescript": "5.2.2"
|
"typescript": "5.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
3722
pnpm-lock.yaml
generated
3722
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
27
src/components/Buttons.tsx
Normal file
27
src/components/Buttons.tsx
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { Button } from '@nextui-org/react'
|
||||||
|
|
||||||
|
export const PdfButton: React.FC<{ label: string; link: string }> = ({
|
||||||
|
label,
|
||||||
|
link,
|
||||||
|
}) => (
|
||||||
|
<Button
|
||||||
|
isDisabled={!link}
|
||||||
|
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
||||||
|
onClick={link ? () => window.open(link) : () => {}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const ZipButton: React.FC<{ label: string; link: string }> = ({
|
||||||
|
label,
|
||||||
|
link,
|
||||||
|
}) => (
|
||||||
|
<Button
|
||||||
|
isDisabled={!link}
|
||||||
|
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
||||||
|
onClick={link ? () => window.open(link) : () => {}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Button>
|
||||||
|
)
|
80
src/components/Selectors.tsx
Normal file
80
src/components/Selectors.tsx
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import { Select, SelectItem } from '@nextui-org/react'
|
||||||
|
import { SelectorProps } from '@/utils/props'
|
||||||
|
|
||||||
|
export const SubjectSelector: React.FC<
|
||||||
|
Pick<SelectorProps, 'selectedSubject' | 'setSelectedSubject' | 'subjects'>
|
||||||
|
> = ({ selectedSubject, setSelectedSubject, subjects }) => (
|
||||||
|
<Select
|
||||||
|
selectionMode='single'
|
||||||
|
disallowEmptySelection={true}
|
||||||
|
label='Tárgy'
|
||||||
|
value={selectedSubject}
|
||||||
|
onChange={(e) => setSelectedSubject(e.target.value)}
|
||||||
|
className='w-56'
|
||||||
|
>
|
||||||
|
{subjects.map((subject) => (
|
||||||
|
<SelectItem key={subject.value} value={subject.value}>
|
||||||
|
{subject.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const YearSelector: React.FC<
|
||||||
|
Pick<SelectorProps, 'selectedYear' | 'setSelectedYear' | 'years'>
|
||||||
|
> = ({ selectedYear, setSelectedYear, years }) => (
|
||||||
|
<Select
|
||||||
|
selectionMode='single'
|
||||||
|
disallowEmptySelection={true}
|
||||||
|
label='Év'
|
||||||
|
value={selectedYear}
|
||||||
|
onChange={(e) => setSelectedYear(e.target.value)}
|
||||||
|
className='w-56'
|
||||||
|
>
|
||||||
|
{years.map((year) => (
|
||||||
|
<SelectItem key={year} value={year}>
|
||||||
|
{year}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const PeriodSelector: React.FC<
|
||||||
|
Pick<SelectorProps, 'selectedPeriod' | 'setSelectedPeriod'>
|
||||||
|
> = ({ selectedPeriod, setSelectedPeriod }) => (
|
||||||
|
<Select
|
||||||
|
selectionMode='single'
|
||||||
|
disallowEmptySelection={true}
|
||||||
|
label='Időszak'
|
||||||
|
value={selectedPeriod}
|
||||||
|
onChange={(e) => setSelectedPeriod(e.target.value)}
|
||||||
|
className='w-56'
|
||||||
|
>
|
||||||
|
<SelectItem key={'tavasz'} value={'tavasz'}>
|
||||||
|
Tavasz
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem key={'osz'} value={'osz'}>
|
||||||
|
Ősz
|
||||||
|
</SelectItem>
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
|
||||||
|
export const LevelSelector: React.FC<
|
||||||
|
Pick<SelectorProps, 'selectedLevel' | 'setSelectedLevel'>
|
||||||
|
> = ({ selectedLevel, setSelectedLevel }) => (
|
||||||
|
<Select
|
||||||
|
selectionMode='single'
|
||||||
|
disallowEmptySelection={true}
|
||||||
|
label='Szint'
|
||||||
|
value={selectedLevel}
|
||||||
|
onChange={(e) => setSelectedLevel(e.target.value)}
|
||||||
|
className='w-56'
|
||||||
|
>
|
||||||
|
<SelectItem key={'kozep'} value={'kozep'}>
|
||||||
|
Közép
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem key={'emelt'} value={'emelt'}>
|
||||||
|
Emelt
|
||||||
|
</SelectItem>
|
||||||
|
</Select>
|
||||||
|
)
|
37
src/hooks/useState.ts
Normal file
37
src/hooks/useState.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
import useYears from '@/hooks/useYears'
|
||||||
|
|
||||||
|
export const useAppState = () => {
|
||||||
|
const [flPdfLink, setflPdfLink] = useState<string>('')
|
||||||
|
const [utPdfLink, setutPdfLink] = useState<string>('')
|
||||||
|
const [flZipLink, setflZipLink] = useState<string>('')
|
||||||
|
const [utZipLink, setutZipLink] = useState<string>('')
|
||||||
|
const [selectedSubject, setSelectedSubject] = useState<string>('')
|
||||||
|
const [selectedYear, setSelectedYear] = useState<string>('')
|
||||||
|
const [selectedPeriod, setSelectedPeriod] = useState<string>('')
|
||||||
|
const [selectedLevel, setSelectedLevel] = useState<string>('')
|
||||||
|
const [years, setYears] = useState<string[]>([])
|
||||||
|
|
||||||
|
useYears(setYears)
|
||||||
|
|
||||||
|
return {
|
||||||
|
flPdfLink,
|
||||||
|
setflPdfLink,
|
||||||
|
utPdfLink,
|
||||||
|
setutPdfLink,
|
||||||
|
flZipLink,
|
||||||
|
setflZipLink,
|
||||||
|
utZipLink,
|
||||||
|
setutZipLink,
|
||||||
|
selectedSubject,
|
||||||
|
setSelectedSubject,
|
||||||
|
selectedYear,
|
||||||
|
setSelectedYear,
|
||||||
|
selectedPeriod,
|
||||||
|
setSelectedPeriod,
|
||||||
|
selectedLevel,
|
||||||
|
setSelectedLevel,
|
||||||
|
years,
|
||||||
|
setYears,
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
export function useYears(
|
export default function useYears(
|
||||||
setYears: React.Dispatch<React.SetStateAction<string[]>>
|
setYears: React.Dispatch<React.SetStateAction<string[]>>
|
||||||
) {
|
) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
|
@ -1,71 +1,56 @@
|
||||||
import { useState, useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
import { ButtonGroup, Divider } from '@nextui-org/react'
|
||||||
|
import { PdfButton, ZipButton } from '@/components/Buttons'
|
||||||
import { Footer } from '@/components/Footer'
|
import { Footer } from '@/components/Footer'
|
||||||
import { subjects } from '@/utils/subjects'
|
import { fetchData } from '@/utils/fetch'
|
||||||
import { useYears } from '@/utils/years'
|
import useYears from '@/hooks/useYears'
|
||||||
|
import { useAppState } from '@/hooks/useState'
|
||||||
import {
|
import {
|
||||||
Select,
|
SubjectSelector,
|
||||||
SelectItem,
|
YearSelector,
|
||||||
Button,
|
PeriodSelector,
|
||||||
ButtonGroup,
|
LevelSelector,
|
||||||
Divider,
|
} from '@/components/Selectors'
|
||||||
} from '@nextui-org/react'
|
import { subjects } from '@/utils/subjects'
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [flPdfLink, setflPdfLink] = useState<string>('')
|
const {
|
||||||
const [utPdfLink, setutPdfLink] = useState<string>('')
|
flPdfLink,
|
||||||
const [flZipLink, setflZipLink] = useState<string>('')
|
setflPdfLink,
|
||||||
const [utZipLink, setutZipLink] = useState<string>('')
|
utPdfLink,
|
||||||
const [selectedSubject, setSelectedSubject] = useState<string>('')
|
setutPdfLink,
|
||||||
const [selectedYear, setSelectedYear] = useState<string>('')
|
flZipLink,
|
||||||
const [selectedPeriod, setSelectedPeriod] = useState<string>('')
|
setflZipLink,
|
||||||
const [selectedLevel, setSelectedLevel] = useState<string>('')
|
utZipLink,
|
||||||
const [years, setYears] = useState<string[]>([])
|
setutZipLink,
|
||||||
|
selectedSubject,
|
||||||
|
setSelectedSubject,
|
||||||
|
selectedYear,
|
||||||
|
setSelectedYear,
|
||||||
|
selectedPeriod,
|
||||||
|
setSelectedPeriod,
|
||||||
|
selectedLevel,
|
||||||
|
setSelectedLevel,
|
||||||
|
years,
|
||||||
|
setYears,
|
||||||
|
} = useAppState()
|
||||||
|
|
||||||
useYears(setYears)
|
useYears(setYears)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
|
||||||
try {
|
|
||||||
let url = `/api/erettsegi?vizsgatargy=${selectedSubject}&ev=${selectedYear}&idoszak=${selectedPeriod}&szint=${selectedLevel}`
|
|
||||||
|
|
||||||
const response = await fetch(url)
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json()
|
|
||||||
|
|
||||||
if (data.utZipUrl && data.flZipUrl) {
|
|
||||||
setflZipLink(data.flZipUrl)
|
|
||||||
setutZipLink(data.utZipUrl)
|
|
||||||
} else {
|
|
||||||
console.error('Nincs érvényes ZIP link a válaszban.')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.utPdfUrl && data.flPdfUrl) {
|
|
||||||
setflPdfLink(data.flPdfUrl)
|
|
||||||
setutPdfLink(data.utPdfUrl)
|
|
||||||
} else {
|
|
||||||
console.error('Nincs érvényes PDF link a válaszban.')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error('Hiba történt az API hívás során.')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Hiba történt az API hívás során.', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedLevel && selectedPeriod && selectedSubject && selectedYear) {
|
if (selectedLevel && selectedPeriod && selectedSubject && selectedYear) {
|
||||||
fetchData()
|
fetchData(
|
||||||
}
|
|
||||||
}, [
|
|
||||||
selectedSubject,
|
selectedSubject,
|
||||||
selectedYear,
|
selectedYear,
|
||||||
selectedPeriod,
|
selectedPeriod,
|
||||||
selectedLevel,
|
selectedLevel,
|
||||||
setflPdfLink,
|
|
||||||
setutPdfLink,
|
|
||||||
setflZipLink,
|
setflZipLink,
|
||||||
setutZipLink,
|
setutZipLink,
|
||||||
])
|
setflPdfLink,
|
||||||
|
setutPdfLink
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className='dark:bg-[#121212] text-foreground bg-background py-5'>
|
<main className='dark:bg-[#121212] text-foreground bg-background py-5'>
|
||||||
|
@ -76,122 +61,47 @@ export default function Home() {
|
||||||
<div className='container mx-auto'>
|
<div className='container mx-auto'>
|
||||||
<div className='flex flex-col items-center justify-center'>
|
<div className='flex flex-col items-center justify-center'>
|
||||||
<div className='mt-5 mb-3'>
|
<div className='mt-5 mb-3'>
|
||||||
<Select
|
<SubjectSelector
|
||||||
selectionMode='single'
|
selectedSubject={selectedSubject}
|
||||||
disallowEmptySelection={true}
|
setSelectedSubject={setSelectedSubject}
|
||||||
label='Tárgy'
|
subjects={subjects}
|
||||||
value={selectedSubject}
|
/>
|
||||||
onChange={(e) => setSelectedSubject(e.target.value)}
|
|
||||||
className='w-56'
|
|
||||||
>
|
|
||||||
{subjects.map((subject) => (
|
|
||||||
<SelectItem key={subject.value} value={subject.value}>
|
|
||||||
{subject.label}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='mb-3'>
|
<div className='mb-3'>
|
||||||
<Select
|
<YearSelector
|
||||||
selectionMode='single'
|
selectedYear={selectedYear}
|
||||||
disallowEmptySelection={true}
|
setSelectedYear={setSelectedYear}
|
||||||
label='Év'
|
years={years}
|
||||||
value={selectedYear}
|
/>
|
||||||
onChange={(e) => setSelectedYear(e.target.value)}
|
|
||||||
className='w-56'
|
|
||||||
>
|
|
||||||
{years.map((year) => (
|
|
||||||
<SelectItem key={year} value={year}>
|
|
||||||
{year}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='mb-3'>
|
<div className='mb-3'>
|
||||||
<Select
|
<PeriodSelector
|
||||||
selectionMode='single'
|
selectedPeriod={selectedPeriod}
|
||||||
disallowEmptySelection={true}
|
setSelectedPeriod={setSelectedPeriod}
|
||||||
label='Időszak'
|
/>
|
||||||
value={selectedPeriod}
|
|
||||||
onChange={(e) => setSelectedPeriod(e.target.value)}
|
|
||||||
className='w-56'
|
|
||||||
>
|
|
||||||
<SelectItem key={'tavasz'} value={'tavasz'}>
|
|
||||||
Tavasz
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem key={'osz'} value={'osz'}>
|
|
||||||
Ősz
|
|
||||||
</SelectItem>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='mb-3'>
|
<div className='mb-3'>
|
||||||
<Select
|
<LevelSelector
|
||||||
selectionMode='single'
|
selectedLevel={selectedLevel}
|
||||||
disallowEmptySelection={true}
|
setSelectedLevel={setSelectedLevel}
|
||||||
label='Szint'
|
/>
|
||||||
value={selectedLevel}
|
|
||||||
onChange={(e) => setSelectedLevel(e.target.value)}
|
|
||||||
className='w-56'
|
|
||||||
>
|
|
||||||
<SelectItem key={'kozep'} value={'kozep'}>
|
|
||||||
Közép
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem key={'emelt'} value={'emelt'}>
|
|
||||||
Emelt
|
|
||||||
</SelectItem>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='space-x-3'>
|
|
||||||
<ButtonGroup>
|
|
||||||
<Button
|
|
||||||
isDisabled={!flPdfLink}
|
|
||||||
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
|
||||||
onClick={flPdfLink ? () => window.open(flPdfLink) : () => {}}
|
|
||||||
>
|
|
||||||
Feladatlap
|
|
||||||
</Button>
|
|
||||||
<Divider orientation='vertical' />
|
|
||||||
<Button
|
|
||||||
isDisabled={!utPdfLink}
|
|
||||||
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
|
||||||
onClick={utPdfLink ? () => window.open(utPdfLink) : () => {}}
|
|
||||||
>
|
|
||||||
Útmutató
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='space-x-3'>
|
<div className='space-x-3'>
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
{selectedSubject === 'inf' ||
|
<PdfButton label='Feladatlap' link={flPdfLink} />
|
||||||
selectedSubject === 'infoism' ||
|
|
||||||
selectedSubject === 'digkult' ? (
|
|
||||||
<Button
|
|
||||||
isDisabled={!flZipLink}
|
|
||||||
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
|
||||||
onClick={
|
|
||||||
flZipLink ? () => window.open(flZipLink) : () => {}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Forrás
|
|
||||||
</Button>
|
|
||||||
) : null}
|
|
||||||
<Divider orientation='vertical' />
|
<Divider orientation='vertical' />
|
||||||
{selectedSubject === 'inf' ||
|
<PdfButton label='Útmutató' link={utPdfLink} />
|
||||||
selectedSubject === 'infoism' ||
|
|
||||||
selectedSubject === 'digkult' ? (
|
|
||||||
<Button
|
|
||||||
isDisabled={!utZipLink}
|
|
||||||
className='w-24 mt-3 text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-2'
|
|
||||||
onClick={
|
|
||||||
utZipLink ? () => window.open(utZipLink) : () => {}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Megoldás
|
|
||||||
</Button>
|
|
||||||
) : null}
|
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
|
{['inf', 'infoism', 'digkult'].includes(selectedSubject) && (
|
||||||
|
<div className='space-x-3'>
|
||||||
|
<ButtonGroup>
|
||||||
|
<ZipButton label='Forrás' link={flZipLink} />
|
||||||
|
<Divider orientation='vertical' />
|
||||||
|
<ZipButton label='Megoldás' link={utZipLink} />
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
38
src/utils/fetch.ts
Normal file
38
src/utils/fetch.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
export const fetchData = async (
|
||||||
|
selectedSubject: string,
|
||||||
|
selectedYear: string,
|
||||||
|
selectedPeriod: string,
|
||||||
|
selectedLevel: string,
|
||||||
|
setflZipLink: (link: string) => void,
|
||||||
|
setutZipLink: (link: string) => void,
|
||||||
|
setflPdfLink: (link: string) => void,
|
||||||
|
setutPdfLink: (link: string) => void
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
let url = `/api/erettsegi?vizsgatargy=${selectedSubject}&ev=${selectedYear}&idoszak=${selectedPeriod}&szint=${selectedLevel}`
|
||||||
|
|
||||||
|
const response = await fetch(url)
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json()
|
||||||
|
|
||||||
|
if (data.utZipUrl && data.flZipUrl) {
|
||||||
|
setflZipLink(data.flZipUrl)
|
||||||
|
setutZipLink(data.utZipUrl)
|
||||||
|
} else {
|
||||||
|
console.error('Nincs érvényes ZIP link a válaszban.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.utPdfUrl && data.flPdfUrl) {
|
||||||
|
setflPdfLink(data.flPdfUrl)
|
||||||
|
setutPdfLink(data.utPdfUrl)
|
||||||
|
} else {
|
||||||
|
console.error('Nincs érvényes PDF link a válaszban.')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Hiba történt az API hívás során.')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Hiba történt az API hívás során.', error)
|
||||||
|
}
|
||||||
|
}
|
12
src/utils/props.ts
Normal file
12
src/utils/props.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export interface SelectorProps {
|
||||||
|
years: string[]
|
||||||
|
subjects: { label: string; value: string }[]
|
||||||
|
selectedSubject: string
|
||||||
|
selectedYear: string
|
||||||
|
selectedPeriod: string
|
||||||
|
selectedLevel: string
|
||||||
|
setSelectedSubject: React.Dispatch<React.SetStateAction<string>>
|
||||||
|
setSelectedYear: React.Dispatch<React.SetStateAction<string>>
|
||||||
|
setSelectedPeriod: React.Dispatch<React.SetStateAction<string>>
|
||||||
|
setSelectedLevel: React.Dispatch<React.SetStateAction<string>>
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue