import { faArrowDown, faArrowUp, faCode, faPause, faPlay, faRotateLeft, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useRef, useState } from "react"; const capitalize = (str: string) => { if (str.length) { return str[0].toLocaleUpperCase() + str.slice(1).toLocaleLowerCase(); } return str; }; interface Timer { name: string; length: number; incrementLength: any; // To-DO: specify type decrementLength: any; // To-DO: specify type colorTheme: string; } function TimerControl({ name, length, incrementLength, decrementLength, colorTheme, }: Timer) { return (

{`${capitalize( name )} Length`}

{length}
); } interface State { session: boolean; running: boolean; sessionLength: number; breakLength: number; countdown: number; bgColor: string; } enum BgColors { Paused = "bg-primary", Session = "bg-success", Break = "bg-warning", } export default function Clock() { const SECS_IN_A_MIN = 60; const DEFAULT_SESSION_LENGTH = 25; const DEFAULT_BREAK_LENGTH = 5; const [state, setState] = useState({ session: true, running: false, sessionLength: DEFAULT_SESSION_LENGTH, breakLength: DEFAULT_BREAK_LENGTH, countdown: DEFAULT_SESSION_LENGTH * SECS_IN_A_MIN, bgColor: BgColors.Paused, }); const beepRef = useRef(null); const countdownRef = useRef(null); const resetCounter = () => { beepRef.current?.pause(); beepRef.current?.fastSeek(0); if (countdownRef.current) clearInterval(countdownRef.current); setState(() => ({ session: true, running: false, sessionLength: DEFAULT_SESSION_LENGTH, breakLength: DEFAULT_BREAK_LENGTH, countdown: DEFAULT_SESSION_LENGTH * SECS_IN_A_MIN, bgColor: BgColors.Paused, })); }; const startCounter = () => { if (countdownRef.current) clearInterval(countdownRef.current); countdownRef.current = setInterval(() => { setState((prevState) => { if (prevState.countdown <= 0) { const wasSession = prevState.session; beepRef.current?.play(); return { ...prevState, session: !wasSession, running: true, countdown: (wasSession ? prevState.breakLength : prevState.sessionLength) * SECS_IN_A_MIN, bgColor: wasSession ? BgColors.Break : BgColors.Session, }; } else { return { ...prevState, countdown: prevState.countdown - 1 }; } }); }, 1000); setState((prevState) => ({ ...prevState, running: true, countdown: prevState.countdown - 1, bgColor: prevState.session ? BgColors.Session : BgColors.Break, })); }; const stopCounter = () => { if (countdownRef.current) clearInterval(countdownRef.current); setState((prevState) => ({ ...prevState, running: false, bgColor: BgColors.Paused, })); }; const incrementSessionLength = () => { setState((prevState) => { if (prevState.running) return prevState; const sessionLength = Math.min(prevState.sessionLength + 1, 60); return { ...prevState, sessionLength: sessionLength, countdown: prevState.session ? sessionLength * SECS_IN_A_MIN : prevState.countdown, }; }); }; const decrementSessionLength = () => { setState((prevState) => { if (prevState.running) return prevState; const sessionLength = Math.max(prevState.sessionLength - 1, 1); return { ...prevState, sessionLength: sessionLength, countdown: prevState.session ? sessionLength * SECS_IN_A_MIN : prevState.countdown, }; }); }; const incrementBreakLength = () => { setState((prevState) => { if (prevState.running) return prevState; const breakLength = Math.min(prevState.breakLength + 1, 60); return { ...prevState, breakLength: breakLength, countdown: prevState.session ? prevState.countdown : breakLength * SECS_IN_A_MIN, }; }); }; const decrementBreakLength = () => { setState((prevState) => { if (prevState.running) return prevState; const breakLength = Math.max(prevState.breakLength - 1, 1); return { ...prevState, breakLength: breakLength, countdown: prevState.session ? prevState.countdown : breakLength * SECS_IN_A_MIN, }; }); }; return (

{state.session ? "Session" : "Break"}

{`${String( Math.floor(state.countdown / SECS_IN_A_MIN) ).padStart(2, "0")}:${String( state.countdown % SECS_IN_A_MIN ).padStart(2, "0")}`}

); }