Kris YotamAlpha Typix Build1671cae2 years agoHistory
182 lines · 5.6 KB · TypeScript
RawDownload
import { resetTest } from "helpers/resetTest";import { useEffect, useState } from "react";import { useDispatch, useSelector } from "react-redux";import {    setTheme,    setTime,    setType,    setWordList,    timerSet,} from "store/actions";import { State } from "store/reducer";import "stylesheets/Header.scss";import "stylesheets/AnimatedTheme.scss"; export interface Options {    time: number[];    theme: string[];    type: string[];} interface AnimationProps {    top: number;    left: number;    theme: string;} export const options: Options = {    time: [15, 30, 45, 60, 120],    theme: [        "khr1st",        "classic-bw",        "slate-grey",        "ocean-breeze",        "sunset-glow",        "forest-green",        "royal-purple",        "coral-reef",        "seafoam-green",    ],    type: [        "words",        "hard-words",        "sentences",        "numbers",        "got",        "javascript",        "python",    ],}; export default function Header() {    const {        preferences: { timeLimit, theme, type },        time: { timerId },    } = useSelector((state: State) => state);    const [animationProps, setAnimationProps] =        useState<AnimationProps | null>();    const dispatch = useDispatch();     useEffect(() => {        const theme = localStorage.getItem("theme") || "default";        const type = localStorage.getItem("type") || "words";        const time = parseInt(localStorage.getItem("time") || "60", 10);        import(`wordlists/${type}.json`).then((words) =>            dispatch(setWordList(words.default))        );        dispatch(timerSet(time));        dispatch(setType(type));        dispatch(setTime(time));        dispatch(setTheme(theme));    }, [dispatch]);     // Set Theme    useEffect(() => {        if (theme) {            document.querySelector(".theme")?.childNodes.forEach((el) => {                if (el instanceof HTMLButtonElement)                    el.classList.remove("selected");            });            document                .querySelector(`button[value="${theme}"]`)                ?.classList.add("selected");            document.body.children[1].classList.remove(...options.theme);            document.body.children[1].classList.add(theme);            localStorage.setItem("theme", theme);        }    }, [dispatch, theme]);     // Set Time    useEffect(() => {        if (timeLimit !== 0) {            document.querySelector(".time")?.childNodes.forEach((el) => {                if (el instanceof HTMLButtonElement)                    el.classList.remove("selected");            });            document                .querySelector(`button[value="${timeLimit}"]`)                ?.classList.add("selected");            dispatch(setTime(timeLimit));            localStorage.setItem("time", `${timeLimit}`);            resetTest();        }    }, [dispatch, timeLimit]);     // Set Type    useEffect(() => {        if (type !== "") {            document.querySelector(".type")?.childNodes.forEach((el) => {                if (el instanceof HTMLButtonElement)                    el.classList.remove("selected");            });            document                .querySelector(`button[value="${type}"]`)                ?.classList.add("selected");            dispatch(setType(type));            localStorage.setItem("type", type);            resetTest();        }    }, [dispatch, type]);     const handleOptions = ({ target, clientX, clientY }: React.MouseEvent) => {        if (target instanceof HTMLButtonElement && target.dataset.option) {            if (target.value === theme || +target.value === timeLimit) {                target.blur();                return;            }            switch (target.dataset.option) {                case "theme":                    setTimeout(() => {                        dispatch(setTheme(target.value));                    }, 750);                    setAnimationProps({                        top: clientY,                        left: clientX,                        theme: target.value,                    });                    break;                case "time":                    dispatch(setTime(+target.value));                    break;                case "type":                    dispatch(setType(target.value));                    break;            }            target.blur();        }    };     return (        <header className={timerId ? "hidden" : undefined}>            <a href="." className="brand">                typix-test            </a>            <div className="buttons">                {Object.entries(options).map(([option, choices]) => (                    <div key={option} className={option}>                        {option}:                        {choices.map((choice: string) => (                            <button                                className="mini"                                key={choice}                                data-option={option}                                value={choice}                                onClick={(e) => handleOptions(e)}>                                {choice}                            </button>                        ))}                    </div>                ))}            </div>            {animationProps ? (                <div                    className={`animated-theme ${animationProps.theme}`}                    style={{                        top: animationProps.top,                        left: animationProps.left,                    }}                    onAnimationEnd={() => setAnimationProps(null)}></div>            ) : null}        </header>    );}