This commit is contained in:
2025-06-19 21:39:32 +02:00
parent 8d12648e3a
commit a0d9bfd5dc
34 changed files with 1645 additions and 7410 deletions
+60 -60
View File
@@ -1,73 +1,73 @@
import { Button } from '@nextui-org/react'
import React, { useState, useEffect, useCallback } from 'react'
import type { ButtonProps } from '@/utils/props'
import type { ButtonColor } from '@/utils/types'
import { Button } from "@heroui/react";
import React, { useCallback, useEffect, useState } from "react";
import type { ButtonProps } from "@/utils/props";
import type { ButtonColor } from "@/utils/types";
const CustomButton: React.FC<ButtonProps> = React.memo(({ label, link }) => {
const [status, setStatus] = useState<number>()
const [isLoading, setIsLoading] = useState<boolean>(false)
const [status, setStatus] = useState<number>();
const [isLoading, setIsLoading] = useState<boolean>(false);
const checkLinkStatus = useCallback(async (): Promise<void> => {
if (link) {
try {
setIsLoading(true)
const response = await fetch(`/api/validate?link=${encodeURI(link)}`)
const data = (await response.json()) as { status: number }
setStatus(data.status)
} catch (error) {
setStatus(500)
} finally {
setIsLoading(false)
}
}
}, [link])
const checkLinkStatus = useCallback(async (): Promise<void> => {
if (link) {
try {
setIsLoading(true);
const response = await fetch(`/api/validate?link=${encodeURI(link)}`);
const data = (await response.json()) as { status: number };
setStatus(data.status);
} catch (_error) {
setStatus(500);
} finally {
setIsLoading(false);
}
}
}, [link]);
useEffect(() => {
void checkLinkStatus()
}, [checkLinkStatus])
useEffect(() => {
void checkLinkStatus();
}, [checkLinkStatus]);
const getColor = useCallback((): ButtonColor => {
switch (true) {
case isLoading:
return 'default'
case status === 200:
return 'primary'
case status === 404:
return 'danger'
default:
return 'default'
}
}, [isLoading, status])
const getColor = useCallback((): ButtonColor => {
switch (true) {
case isLoading:
return "default";
case status === 200:
return "primary";
case status === 404:
return "danger";
default:
return "default";
}
}, [isLoading, status]);
const handleClick = useCallback(() => {
if (status === 200 && link) {
window.open(link)
} else {
console.error('A hivatkozás nem elérhető.')
}
}, [status, link])
const handleClick = useCallback(() => {
if (status === 200 && link) {
window.open(link);
} else {
console.error("A hivatkozás nem elérhető.");
}
}, [status, link]);
return (
<Button
isDisabled={status !== 200 || !link || isLoading}
isLoading={isLoading}
className='w-28 mt-3 text-sm font-bold py-2 px-2'
color={getColor()}
onClick={handleClick}
>
{label}
</Button>
)
})
return (
<Button
isDisabled={status !== 200 || !link || isLoading}
isLoading={isLoading}
className="w-28 mt-3 text-sm font-bold py-2 px-2"
color={getColor()}
onPress={handleClick}
>
{label}
</Button>
);
});
export const PdfButton: React.FC<ButtonProps> = React.memo(
({ label, link }) => <CustomButton label={label} link={link} />
)
({ label, link }) => <CustomButton label={label} link={link} />,
);
export const ZipButton: React.FC<ButtonProps> = React.memo(
({ label, link }) => <CustomButton label={label} link={link} />
)
({ label, link }) => <CustomButton label={label} link={link} />,
);
export const Mp3Button: React.FC<ButtonProps> = React.memo(
({ label, link }) => <CustomButton label={label} link={link} />
)
({ label, link }) => <CustomButton label={label} link={link} />,
);
+9 -9
View File
@@ -1,11 +1,11 @@
import { ThemeSwitcher } from '@/components/ThemeSwitcher'
import { Source } from '@/components/Source'
import { Source } from "@/components/Source";
import { ThemeSwitcher } from "@/components/ThemeSwitcher";
export const Footer = () => {
return (
<div className='fixed bottom-0 py-5 left-0 right-0 text-center space-x-5'>
<Source />
<ThemeSwitcher />
</div>
)
}
return (
<div className="fixed bottom-0 py-5 left-0 right-0 text-center space-x-5">
<Source />
<ThemeSwitcher />
</div>
);
};
+65 -68
View File
@@ -1,80 +1,77 @@
import { Select, SelectItem } from '@nextui-org/react'
import type { SelectorProps } from '@/utils/props'
import { Select, SelectItem } from "@heroui/react";
import type { SelectorProps } from "@/utils/props";
import type { ChangeEvent } from "react";
export const SubjectSelector: React.FC<
Pick<SelectorProps, 'selectedSubject' | 'setSelectedSubject' | 'subjects'>
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>
)
<Select
selectionMode="single"
disallowEmptySelection={true}
label="Tárgy"
value={selectedSubject}
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setSelectedSubject(e.target.value)
}
className="w-56"
>
{subjects.map((subject) => (
<SelectItem key={subject.value}>{subject.label}</SelectItem>
))}
</Select>
);
export const YearSelector: React.FC<
Pick<SelectorProps, 'selectedYear' | 'setSelectedYear' | 'years'>
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>
)
<Select
selectionMode="single"
disallowEmptySelection={true}
label="Év"
value={selectedYear}
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setSelectedYear(e.target.value)
}
className="w-56"
>
{years.map((year) => (
<SelectItem key={year}>{year}</SelectItem>
))}
</Select>
);
export const PeriodSelector: React.FC<
Pick<SelectorProps, 'selectedPeriod' | 'setSelectedPeriod'>
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>
)
<Select
selectionMode="single"
disallowEmptySelection={true}
label="Időszak"
value={selectedPeriod}
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setSelectedPeriod(e.target.value)
}
className="w-56"
>
<SelectItem key={"tavasz"}>Tavasz</SelectItem>
<SelectItem key={"osz"}>Ősz</SelectItem>
</Select>
);
export const LevelSelector: React.FC<
Pick<SelectorProps, 'selectedLevel' | 'setSelectedLevel'>
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>
)
<Select
selectionMode="single"
disallowEmptySelection={true}
label="Szint"
value={selectedLevel}
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
setSelectedLevel(e.target.value)
}
className="w-56"
>
<SelectItem key={"kozep"}>Közép</SelectItem>
<SelectItem key={"emelt"}>Emelt</SelectItem>
</Select>
);
+14 -14
View File
@@ -1,16 +1,16 @@
import { VscGithubInverted } from 'react-icons/vsc'
import { Button } from '@nextui-org/button'
import { Button } from "@heroui/button";
import { VscGithubInverted } from "react-icons/vsc";
export const Source = () => {
return (
<Button
aria-label='Source Code'
size='sm'
onClick={() =>
window.open('https://github.com/skidoodle/erettsegi-browser')
}
>
<VscGithubInverted size={20} />
</Button>
)
}
return (
<Button
aria-label="Source Code"
size="sm"
onPress={() =>
window.open("https://github.com/skidoodle/erettsegi-browser")
}
>
<VscGithubInverted size={20} />
</Button>
);
};
+17 -17
View File
@@ -1,21 +1,21 @@
import { VscColorMode } from 'react-icons/vsc'
import { Button } from '@nextui-org/button'
import { useTheme } from 'next-themes'
import { Button } from "@heroui/button";
import { useTheme } from "next-themes";
import { VscColorMode } from "react-icons/vsc";
export const ThemeSwitcher = () => {
const { theme, setTheme } = useTheme()
const { theme, setTheme } = useTheme();
const toggle = () => {
setTheme(theme === 'light' ? 'dark' : 'light')
}
const toggle = () => {
setTheme(theme === "light" ? "dark" : "light");
};
return (
<Button aria-label='Switch Theme' size='sm' onClick={() => toggle()}>
{theme === 'light' ? (
<VscColorMode style={{ fill: 'black' }} size={20} />
) : (
<VscColorMode size={20} key={'dark'} />
)}
</Button>
)
}
return (
<Button aria-label="Switch Theme" size="sm" onPress={() => toggle()}>
{theme === "light" ? (
<VscColorMode style={{ fill: "black" }} size={20} />
) : (
<VscColorMode size={20} key={"dark"} />
)}
</Button>
);
};