diff --git a/src/components/toolbox/pomodoro/button/button.module.css b/src/components/toolbox/pomodoro/button/button.module.css new file mode 100644 index 0000000..6b7c628 --- /dev/null +++ b/src/components/toolbox/pomodoro/button/button.module.css @@ -0,0 +1,19 @@ +.button { + display: flex; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + font-size: var(--font-xsm); + color: var(--color-foreground); + cursor: pointer; + background-color: var(--color-neutral-100); + border: 1px solid var(--color-neutral-200); + border-radius: 4px; + outline: none; + transition: 0.2s; + + &:hover { + background-color: var(--color-neutral-200); + } +} diff --git a/src/components/toolbox/pomodoro/button/button.tsx b/src/components/toolbox/pomodoro/button/button.tsx new file mode 100644 index 0000000..5ecef5d --- /dev/null +++ b/src/components/toolbox/pomodoro/button/button.tsx @@ -0,0 +1,19 @@ +import { Tooltip } from '@/components/tooltip'; + +import styles from './button.module.css'; + +interface ButtonProps { + icon: React.ReactElement; + onClick: () => void; + tooltip: string; +} + +export function Button({ icon, onClick, tooltip }: ButtonProps) { + return ( + + + {icon} + + + ); +} diff --git a/src/components/toolbox/pomodoro/button/index.ts b/src/components/toolbox/pomodoro/button/index.ts new file mode 100644 index 0000000..a039b75 --- /dev/null +++ b/src/components/toolbox/pomodoro/button/index.ts @@ -0,0 +1 @@ +export { Button } from './button'; diff --git a/src/components/toolbox/pomodoro/pomodoro.module.css b/src/components/toolbox/pomodoro/pomodoro.module.css index 8f414f5..54351e5 100644 --- a/src/components/toolbox/pomodoro/pomodoro.module.css +++ b/src/components/toolbox/pomodoro/pomodoro.module.css @@ -1 +1,17 @@ -/* TODO */ +.control { + display: flex; + align-items: center; + justify-content: space-between; + margin-top: 8px; + + & .completed { + font-size: var(--font-xsm); + color: var(--color-foreground-subtle); + } + + & .buttons { + display: flex; + column-gap: 4px; + align-items: center; + } +} diff --git a/src/components/toolbox/pomodoro/pomodoro.tsx b/src/components/toolbox/pomodoro/pomodoro.tsx index 22c88c9..a61314c 100644 --- a/src/components/toolbox/pomodoro/pomodoro.tsx +++ b/src/components/toolbox/pomodoro/pomodoro.tsx @@ -1,10 +1,12 @@ -import { useState } from 'react'; +import { useState, useEffect, useRef, useMemo } from 'react'; +import { FaUndo, FaPlay, FaPause } from 'react-icons/fa/index'; import { Modal } from '@/components/modal'; import { Tabs } from './tabs'; import { Timer } from './timer'; +import { Button } from './button'; -// import styles from './pomodoro.module.css'; +import styles from './pomodoro.module.css'; interface PomodoroProps { onClose: () => void; @@ -13,18 +15,84 @@ interface PomodoroProps { export function Pomodoro({ onClose, show }: PomodoroProps) { const [selectedTab, setSelectedTab] = useState('pomodoro'); + const [running, setRunning] = useState(false); + const [timer, setTimer] = useState(10); + const interval = useRef | null>(null); - const tabs = [ - { id: 'pomodoro', label: 'Pomodoro' }, - { id: 'short', label: 'Break' }, - { id: 'long', label: 'Long Break' }, - ]; + const tabs = useMemo( + () => [ + { id: 'pomodoro', label: 'Pomodoro', time: 60 }, + { id: 'short', label: 'Break', time: 60 }, + { id: 'long', label: 'Long Break', time: 60 }, + ], + [], + ); + + useEffect(() => { + if (running) { + if (interval.current) clearInterval(interval.current); + + interval.current = setInterval(() => { + setTimer(prev => prev - 1); + }, 1000); + } else { + if (interval.current) clearInterval(interval.current); + } + }, [running]); + + useEffect(() => { + if (timer <= 0) { + if (interval.current) clearInterval(interval.current); + + setRunning(false); + } + }, [timer]); + + useEffect(() => { + const time = tabs.find(tab => tab.id === selectedTab)?.time || 10; + + if (interval.current) clearInterval(interval.current); + + setRunning(false); + setTimer(time); + }, [selectedTab, tabs]); + + const toggleRunning = () => { + if (running) setRunning(false); + else if (timer <= 0) { + const time = tabs.find(tab => tab.id === selectedTab)?.time || 10; + + setTimer(time); + setRunning(true); + } else setRunning(true); + }; + + const restart = () => { + if (interval.current) clearInterval(interval.current); + + const time = tabs.find(tab => tab.id === selectedTab)?.time || 10; + + setRunning(false); + setTimer(time); + }; return ( Pomodoro Timer - + + + + 0 completed + + } tooltip="Restart" onClick={restart} /> + : } + tooltip={running ? 'Pause' : 'Start'} + onClick={toggleRunning} + /> + + ); } diff --git a/src/components/toolbox/pomodoro/timer/timer.tsx b/src/components/toolbox/pomodoro/timer/timer.tsx index 21aa1f5..81a25b2 100644 --- a/src/components/toolbox/pomodoro/timer/timer.tsx +++ b/src/components/toolbox/pomodoro/timer/timer.tsx @@ -1,5 +1,15 @@ +import { padNumber } from '@/helpers/number'; + import styles from './timer.module.css'; -export function Timer() { - return 25:00; +interface TimerProps { + timer: number; +} + +export function Timer({ timer }: TimerProps) { + return ( + + {padNumber(Math.floor(timer / 60))}:{padNumber(timer % 60)} + + ); } diff --git a/src/helpers/number.ts b/src/helpers/number.ts new file mode 100644 index 0000000..e904111 --- /dev/null +++ b/src/helpers/number.ts @@ -0,0 +1,3 @@ +export function padNumber(number: number, maxLength: number = 2): string { + return number.toString().padStart(maxLength, '0'); +}
0 completed