101 lines
3.3 KiB
TypeScript
101 lines
3.3 KiB
TypeScript
import LightButton from "@/components/buttons/LightButton";
|
|
import { WordData } from "@/lib/interfaces";
|
|
import { Dispatch, SetStateAction, useState } from "react";
|
|
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
|
|
import { getTTSAudioUrl } from "@/lib/utils";
|
|
import { VOICES } from "@/config/locales";
|
|
|
|
import { useTranslations } from "next-intl";
|
|
|
|
interface WordBoardProps {
|
|
children: React.ReactNode;
|
|
}
|
|
function WordBoard({ children }: WordBoardProps) {
|
|
return (
|
|
<div className="text-nowrap w-full h-36 border border-white rounded flex justify-center items-center text-4xl md:text-6xl font-serif overflow-x-auto">
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface Props {
|
|
wordData: WordData;
|
|
setPage: Dispatch<SetStateAction<"start" | "main" | "edit">>;
|
|
}
|
|
export default function Start({ wordData, setPage }: Props) {
|
|
const t = useTranslations("memorize.start");
|
|
const [display, setDisplay] = useState<"ask" | "show">("ask");
|
|
const [wordPair, setWordPair] = useState(
|
|
wordData.wordPairs[Math.floor(Math.random() * wordData.wordPairs.length)],
|
|
);
|
|
const [reverse, setReverse] = useState(false);
|
|
const [dictation, setDictation] = useState(false);
|
|
const { load, play } = useAudioPlayer();
|
|
const show = () => {
|
|
setDisplay("show");
|
|
};
|
|
const next = async () => {
|
|
setDisplay("ask");
|
|
const newWordPair =
|
|
wordData.wordPairs[Math.floor(Math.random() * wordData.wordPairs.length)];
|
|
setWordPair(newWordPair);
|
|
if (dictation)
|
|
await load(
|
|
await getTTSAudioUrl(
|
|
newWordPair[reverse ? 1 : 0],
|
|
VOICES.find((v) => v.locale === wordData.locales[reverse ? 1 : 0])!
|
|
.short_name,
|
|
),
|
|
).then(play);
|
|
};
|
|
return (
|
|
<div className="w-screen flex justify-center items-center">
|
|
<div className="flex-col flex items-center h-96">
|
|
<div className="flex-1 w-[95dvw] md:w-fit p-4 gap-4 flex flex-col overflow-x-auto">
|
|
{dictation ? (
|
|
<>
|
|
{display === "show" && (
|
|
<>
|
|
<WordBoard>{wordPair[reverse ? 1 : 0]}</WordBoard>
|
|
<WordBoard>{wordPair[reverse ? 0 : 1]}</WordBoard>
|
|
</>
|
|
)}
|
|
</>
|
|
) : (
|
|
<>
|
|
<WordBoard>{wordPair[reverse ? 1 : 0]}</WordBoard>
|
|
{display === "show" && (
|
|
<WordBoard>{wordPair[reverse ? 0 : 1]}</WordBoard>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
<div className="w-full flex items-center justify-center">
|
|
<div className="flex gap-2 justify-center items-center w-fit font-mono flex-wrap">
|
|
{display === "ask" ? (
|
|
<LightButton onClick={show}>{t("show")}</LightButton>
|
|
) : (
|
|
<LightButton onClick={next}>{t("next")}</LightButton>
|
|
)}
|
|
<LightButton
|
|
onClick={() => setReverse(!reverse)}
|
|
selected={reverse}
|
|
>
|
|
{t("reverse")}
|
|
</LightButton>
|
|
<LightButton
|
|
onClick={() => setDictation(!dictation)}
|
|
selected={dictation}
|
|
>
|
|
{t("dictation")}
|
|
</LightButton>
|
|
<LightButton onClick={() => setPage("main")}>
|
|
{t("back")}
|
|
</LightButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|