From 831a190c599b97be13c30efbe300381108ed9240 Mon Sep 17 00:00:00 2001 From: Evan Trujillo Date: Wed, 24 Jan 2024 18:15:17 +0900 Subject: [PATCH] Add timer settings (#47) * Move pomodoro-status file location * Add shadcn input component * Update input source classes * Add pomodoro timer setting * Fixed tailwind class order * WIP: Introduce redux to timer settings * Handle updating values * Add reducer * Handle data in settings modal * Complete implemention of redux * Remove unwanted commented out code --- src/app/page.tsx | 2 +- src/components/pomodoro/pomodoro-settings.tsx | 12 ++- .../{ => pomodoro}/pomodoro-status.tsx | 4 +- .../pomodoro/pomodoro-timer-settings.tsx | 100 ++++++++++++++++++ src/components/pomodoro/pomodoro-timer.tsx | 12 +-- src/components/ui/input.tsx | 25 +++++ src/lib/redux/slices/pomodoroSettingsSlice.ts | 4 + 7 files changed, 148 insertions(+), 11 deletions(-) rename src/components/{ => pomodoro}/pomodoro-status.tsx (96%) create mode 100644 src/components/pomodoro/pomodoro-timer-settings.tsx create mode 100644 src/components/ui/input.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx index f3d4416..2833546 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,6 @@ import Pomodoro from '@/components/pomodoro/pomodoro'; import Logo from '../components/logo'; -import PomodoroStatus from '@/components/pomodoro-status'; +import PomodoroStatus from '@/components/pomodoro/pomodoro-status'; export default function Home() { return ( diff --git a/src/components/pomodoro/pomodoro-settings.tsx b/src/components/pomodoro/pomodoro-settings.tsx index 77705f7..681721b 100644 --- a/src/components/pomodoro/pomodoro-settings.tsx +++ b/src/components/pomodoro/pomodoro-settings.tsx @@ -5,6 +5,7 @@ import { ReactElement, useState } from 'react'; import Image from 'next/image'; import PomodoroColourSettings from '@/components/pomodoro/pomodoro-colour-settings'; import PomodoroFontSettings from '@/components/pomodoro/pomodoro-font-settings'; +import PomodoroTimerSettings, { PomodoroTimerData } from './pomodoro-timer-settings'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { pomodoroSettingsSlice } from '@/lib/redux/slices/pomodoroSettingsSlice'; @@ -12,10 +13,11 @@ import { useDispatch, useSelector } from '@/lib/redux/store'; export default function PomodoroSettings(): ReactElement { const dispatch = useDispatch(); - const { colour, font } = useSelector((state) => state.pomodoroSettings); + const { colour, font, time } = useSelector((state) => state.pomodoroSettings); const [selectedFont, setSelectedFont] = useState(font); const [selectedColour, setSelectedColour] = useState(colour); + const [selectedTime, setSelectedTime] = useState(time); const [open, setOpen] = useState(false); const handleFontChange = (font: string) => { @@ -26,10 +28,15 @@ export default function PomodoroSettings(): ReactElement { setSelectedColour(colour); }; + const handleTimeChange = (time: PomodoroTimerData) => { + setSelectedTime(time) + } + const handleApplyNewSettings = () => { const settings = { font: selectedFont, colour: selectedColour, + time: selectedTime }; dispatch(pomodoroSettingsSlice.actions.updateAllSettings(settings)); setOpen(false); @@ -40,10 +47,11 @@ export default function PomodoroSettings(): ReactElement { settings - + Edit profile + diff --git a/src/components/pomodoro-status.tsx b/src/components/pomodoro/pomodoro-status.tsx similarity index 96% rename from src/components/pomodoro-status.tsx rename to src/components/pomodoro/pomodoro-status.tsx index 9b7277d..1f1418f 100644 --- a/src/components/pomodoro-status.tsx +++ b/src/components/pomodoro/pomodoro-status.tsx @@ -1,8 +1,8 @@ 'use client'; import { ReactElement } from 'react'; -import { Label } from './ui/label'; -import { RadioGroup, RadioGroupItem } from './ui/radio-group'; +import { Label } from '../ui/label'; +import { RadioGroup, RadioGroupItem } from '../ui/radio-group'; import { PomodoroStatus } from '@/lib/redux/slices/pomodoroStatusSlice'; import { pomodoroStatusSlice } from '@/lib/redux/slices/pomodoroStatusSlice'; import { useSelector, useDispatch, ReduxState } from '@/lib/redux/store'; diff --git a/src/components/pomodoro/pomodoro-timer-settings.tsx b/src/components/pomodoro/pomodoro-timer-settings.tsx new file mode 100644 index 0000000..ec43b67 --- /dev/null +++ b/src/components/pomodoro/pomodoro-timer-settings.tsx @@ -0,0 +1,100 @@ +import { ChangeEvent, useState } from 'react'; +import { Colours } from '@/lib/colours'; +import { ReduxState, useSelector } from '@/lib/redux/store'; +import { Input } from '../ui/input'; +import { Label } from '../ui/label'; + +export interface PomodoroTimerData { + pomodoro: number; + shortBreak: number; + longBreak: number; +} + +interface PomodoroTimerSettingsProps { + onTimerChange: (updatedTimerData: PomodoroTimerData) => void; +} + +export default function PomodoroTimerSettings({ onTimerChange }: PomodoroTimerSettingsProps) { + const { colour, time } = useSelector((state: ReduxState) => state.pomodoroSettings); + const [selectedTime, setSelectedTime] = useState(time); + const inputRules = { + min: 5, + max: 60, + step: 5, + }; + + const updateTimeValues = (callback: (prevSelectedTime: PomodoroTimerData) => Partial) => { + const updatedProperties = callback(selectedTime); + + setSelectedTime((prevSelectedTime) => ({ + ...prevSelectedTime, + ...updatedProperties, + })); + + onTimerChange({ ...selectedTime, ...updatedProperties }); + }; + + const handleTimeChange = (event: ChangeEvent) => { + const { name, value } = event.target; + updateTimeValues(() => ({ [name]: value })); + }; + + function setRingOffsetColor(colour: string) { + switch (colour) { + case Colours.SecondaryAqua: + return 'focus:border-secondary-aqua'; + case Colours.SecondaryPurple: + return 'focus:border-secondary-purple'; + } + return 'focus:border-secondary-peach'; + } + + return ( +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+ ); +} diff --git a/src/components/pomodoro/pomodoro-timer.tsx b/src/components/pomodoro/pomodoro-timer.tsx index e616e2c..9c209ff 100644 --- a/src/components/pomodoro/pomodoro-timer.tsx +++ b/src/components/pomodoro/pomodoro-timer.tsx @@ -10,12 +10,12 @@ import { CircularTimer } from './circular-progress'; export default function PomodoroTimer(): ReactElement { const { status } = useSelector((state: ReduxState) => state.pomodoroStatus); - const { colour } = useSelector((state: ReduxState) => state.pomodoroSettings); + const { colour, time } = useSelector((state: ReduxState) => state.pomodoroSettings); const dispatch = useDispatch(); - const pomodoroTime = 1500; - const shortBreakTime = 300; - const longBreakTime = 900; + const pomodoroTime = time.pomodoro * 60; + const shortBreakTime = time.shortBreak * 60; + const longBreakTime = time.longBreak * 60; const intervalId = useRef(null); const [pomodoroCount, setPomodoroCount] = useState(1); @@ -76,14 +76,14 @@ import { CircularTimer } from './circular-progress'; setTimeRemaining(longBreakTime); setIsFocusTime(false); } - }, [status]); + }, [longBreakTime, pomodoroTime, shortBreakTime, status]); useEffect(() => { if (timeRemaining === 0) { if (intervalId.current !== null) { clearInterval(intervalId.current); } - // clearInterval(intervalId.current); + intervalId.current = null; if (isFocusTime && pomodoroCount == 4) { dispatch(pomodoroStatusSlice.actions.selectedTimer('long')); diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..d787361 --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/src/lib/redux/slices/pomodoroSettingsSlice.ts b/src/lib/redux/slices/pomodoroSettingsSlice.ts index 4284a1a..404ce4e 100644 --- a/src/lib/redux/slices/pomodoroSettingsSlice.ts +++ b/src/lib/redux/slices/pomodoroSettingsSlice.ts @@ -1,14 +1,17 @@ import { Colours } from '@/lib/colours'; import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { PomodoroTimerData } from '@/components/pomodoro/pomodoro-timer-settings'; interface PomodoroSettingsSliceState { font: string; colour: string; + time: PomodoroTimerData; } const InitialSettingsState: PomodoroSettingsSliceState = { font: 'font-kumbh', colour: Colours.SecondaryPeach, + time: { pomodoro: 25, shortBreak: 5, longBreak: 15 } }; export const pomodoroSettingsSlice = createSlice({ @@ -24,6 +27,7 @@ export const pomodoroSettingsSlice = createSlice({ updateAllSettings: (state, action: PayloadAction) => { state.font = action.payload.font; state.colour = action.payload.colour; + state.time = action.payload.time; }, }, });