From 699d89d201ee360c173f79af0e80aadcc77ddb17 Mon Sep 17 00:00:00 2001 From: TobbleCobble Date: Thu, 11 Dec 2025 15:17:26 +0000 Subject: [PATCH 1/9] added timer page that shows a countdown to unfinished tasks --- client/src/components/ui/countdown.tsx | 50 +++++++++++++++++++++++ client/src/components/ui/timer.tsx | 27 +++++++++++++ client/src/pages/timer.tsx | 56 ++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 client/src/components/ui/countdown.tsx create mode 100644 client/src/components/ui/timer.tsx create mode 100644 client/src/pages/timer.tsx diff --git a/client/src/components/ui/countdown.tsx b/client/src/components/ui/countdown.tsx new file mode 100644 index 0000000..f397d4e --- /dev/null +++ b/client/src/components/ui/countdown.tsx @@ -0,0 +1,50 @@ +import React, { useEffect,useState } from "react"; + +import Timer from "./timer"; + +interface Timed { + taskTime: string; +} + +const Countdown = ({ taskTime }: Timed) => { + const [timeRemaining, setTimeRemaining] = useState(0); + + useEffect(() => { + if (taskTime) { + const countdownInterval = setInterval(() => { + const [eventHours, eventMins, eventSec] = taskTime + .split(":") + .map(Number); + const d = new Date(); + let remainingTime = + (eventHours - d.getHours()) * 60 * 60 + + (eventMins - d.getMinutes()) * 60 + + (eventSec - d.getSeconds()); + + if (remainingTime <= 0) { + remainingTime = 0; + clearInterval(countdownInterval); + } + + setTimeRemaining(remainingTime); + }, 1000); + + return () => clearInterval(countdownInterval); + } + }, [taskTime, timeRemaining]); + + return ( + <> + {timeRemaining > 0 ? ( +
+

TIME LEFT

+
{Timer(timeRemaining)}
+
+ ) : ( +
+ )} + + ); +}; + +export default Countdown; diff --git a/client/src/components/ui/timer.tsx b/client/src/components/ui/timer.tsx new file mode 100644 index 0000000..06eabda --- /dev/null +++ b/client/src/components/ui/timer.tsx @@ -0,0 +1,27 @@ +const Timer = (timeRemaining: number) => { + const formatTime = (time: number) => { + const seconds = Math.floor(time % 60); + const minutes = Math.floor((time / 60) % 60); + const hours = Math.floor((time / (60 * 60)) % 24); + + return ( +
+
+ {hours.toString().padStart(2, "0")} + : + {minutes.toString().padStart(2, "0")} + : + {seconds.toString().padStart(2, "0")} +
+
+ ); + }; + + return ( +
+ {formatTime(timeRemaining)} +
+ ); +}; + +export default Timer; diff --git a/client/src/pages/timer.tsx b/client/src/pages/timer.tsx new file mode 100644 index 0000000..30b13b3 --- /dev/null +++ b/client/src/pages/timer.tsx @@ -0,0 +1,56 @@ +import React, { useState } from "react"; + +import Countdown from "@/components/ui/countdown"; + +const CountdownTimer = () => { + const [tasks, setTasks] = useState([]); + + interface Tasks { + id: number; + end_time: string; + } + + async function refreshTasks() { + try { + const response = await fetch("http://localhost:8000/api/planner/time/"); + if (!response.ok) { + throw new Error(`Response status: ${response.status}`); + } + + const result = await response.json(); + console.log(result); + setTasks(result); + console.log(tasks); + } catch (error) { + console.error(error); + } + } + + // check for tasks + // direct to make task page if no tasks + // refresh timer to check for tasks + // play timer if there is a current task + + // lonk in button + // lonk out + + return ( +
+ + +
+ ); +}; + +export default CountdownTimer; From 6c1e52a8dc0764b552d87b562a1e782929d8f070 Mon Sep 17 00:00:00 2001 From: TobbleCobble Date: Fri, 12 Dec 2025 09:09:38 +0000 Subject: [PATCH 2/9] only shows active tasks --- client/src/components/ui/currentTask.tsx | 82 ++++++++++++++++++++++++ client/src/pages/timer.tsx | 67 +++++++++++++------ 2 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 client/src/components/ui/currentTask.tsx diff --git a/client/src/components/ui/currentTask.tsx b/client/src/components/ui/currentTask.tsx new file mode 100644 index 0000000..7e37015 --- /dev/null +++ b/client/src/components/ui/currentTask.tsx @@ -0,0 +1,82 @@ +import { useEffect, useState } from "react"; + +import Countdown from "./countdown"; + +interface Task { + id: number; + start_time: string; + end_time: string; +} + +interface Tasks { + tasks: Task[]; +} + +const CurrentTask = ({ tasks }: Tasks) => { + const [currentTasks, setCurrentTasks] = useState([]); + + useEffect(() => { + function getCurrentTask() { + setCurrentTasks([]); + tasks.forEach((task) => { + const [startHours, startMins, startSec] = task.start_time + .split(":") + .map(Number); + const [endHours, endMins, endSec] = task.end_time + .split(":") + .map(Number); + + const d = new Date(); + const start_time = startHours * 60 * 60 + startMins * 60 + startSec; + const end_time = endHours * 60 * 60 + endMins * 60 + endSec; + const cur_time = + d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); + console.log( + startHours, + " ", + endHours, + " ", + endHours, + " ", + endMins, + " ", + d.getHours(), + " ", + d.getMinutes(), + ); + console.log(start_time, " ", end_time, " ", cur_time); + + if (start_time <= cur_time && end_time >= cur_time) { + setCurrentTasks((prevTasks) => [...prevTasks, task]); + } + }); + } + + getCurrentTask(); + }, [tasks]); + + return ( + <> +
    + {currentTasks.length <= 0 ? ( + <> +
    +

    NO CURRENT TASKS

    +
    MAKE ONE?
    +
    + + ) : ( + <> + {currentTasks.map((task: Task) => ( +
  • + +
  • + ))} + + )} +
+ + ); +}; + +export default CurrentTask; diff --git a/client/src/pages/timer.tsx b/client/src/pages/timer.tsx index 30b13b3..e25af55 100644 --- a/client/src/pages/timer.tsx +++ b/client/src/pages/timer.tsx @@ -1,16 +1,14 @@ import React, { useState } from "react"; -import Countdown from "@/components/ui/countdown"; +import CurrentTask from "@/components/ui/currentTask"; const CountdownTimer = () => { const [tasks, setTasks] = useState([]); - - interface Tasks { - id: number; - end_time: string; - } + const [loading, setLoading] = useState(false); async function refreshTasks() { + setLoading(true); + try { const response = await fetch("http://localhost:8000/api/planner/time/"); if (!response.ok) { @@ -21,6 +19,7 @@ const CountdownTimer = () => { console.log(result); setTasks(result); console.log(tasks); + setLoading(false); } catch (error) { console.error(error); } @@ -35,20 +34,48 @@ const CountdownTimer = () => { // lonk out return ( -
- -
    - {tasks.map((task: Tasks) => ( -
  • - -
  • - ))} -
+
+
+ {loading ? ( +
+ +
+ ) : ( + + )} + +
+ +
+
); }; From bee1fc05b5429ecc808e12157963175f3a9160be Mon Sep 17 00:00:00 2001 From: TobbleCobble Date: Sat, 13 Dec 2025 06:53:36 +0000 Subject: [PATCH 3/9] moving files --- client/src/components/ui/countdown.tsx | 11 ++++- client/src/components/ui/currentTask.tsx | 22 +++++++++ client/src/components/ui/timeDisplay.tsx | 55 +++++++++++++++++++++++ client/src/pages/{timer.tsx => focus.tsx} | 55 +++++++++++++++++++++-- 4 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 client/src/components/ui/timeDisplay.tsx rename client/src/pages/{timer.tsx => focus.tsx} (67%) diff --git a/client/src/components/ui/countdown.tsx b/client/src/components/ui/countdown.tsx index f397d4e..217b02f 100644 --- a/client/src/components/ui/countdown.tsx +++ b/client/src/components/ui/countdown.tsx @@ -1,4 +1,4 @@ -import React, { useEffect,useState } from "react"; +import React, { ChangeEvent, useEffect,useState } from "react"; import Timer from "./timer"; @@ -6,8 +6,16 @@ interface Timed { taskTime: string; } +// in future use task data as input + const Countdown = ({ taskTime }: Timed) => { const [timeRemaining, setTimeRemaining] = useState(0); + const [completed, setCompleted] = useState(false); + + const completeTask = (event : ChangeEvent) => { + // send post request to update db + setCompleted(event.target.checked); + } useEffect(() => { if (taskTime) { @@ -39,6 +47,7 @@ const Countdown = ({ taskTime }: Timed) => {

TIME LEFT

{Timer(timeRemaining)}
+
) : (
diff --git a/client/src/components/ui/currentTask.tsx b/client/src/components/ui/currentTask.tsx index 7e37015..8cb03a7 100644 --- a/client/src/components/ui/currentTask.tsx +++ b/client/src/components/ui/currentTask.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import Countdown from "./countdown"; +import TimeDisplay from "./timeDisplay"; interface Task { id: number; @@ -14,6 +15,13 @@ interface Tasks { const CurrentTask = ({ tasks }: Tasks) => { const [currentTasks, setCurrentTasks] = useState([]); + const [currentTask, setCurrentTask] = useState( + { + id : 1, + start_time : "00:00:00", + end_time : "00:00:00" + } + ); useEffect(() => { function getCurrentTask() { @@ -50,11 +58,18 @@ const CurrentTask = ({ tasks }: Tasks) => { setCurrentTasks((prevTasks) => [...prevTasks, task]); } }); + setCurrentTask(currentTasks[0]); } getCurrentTask(); }, [tasks]); + const updateTask = (status : string) => { + if (status == "finished") { + setCurrentTask(currentTasks[0]); + } + } + return ( <>
    @@ -75,6 +90,13 @@ const CurrentTask = ({ tasks }: Tasks) => { )}
+
+ {currentTasks.length > 0 ? ( + + ):( + <> + )} +
); }; diff --git a/client/src/components/ui/timeDisplay.tsx b/client/src/components/ui/timeDisplay.tsx new file mode 100644 index 0000000..bbf8845 --- /dev/null +++ b/client/src/components/ui/timeDisplay.tsx @@ -0,0 +1,55 @@ +import React, { useEffect, useState } from "react"; +import { finished } from "stream"; +import Timer from "./timer"; + +interface TimeDisplayProps { + statusSignal : (data: string) => void; + end_time : string; +} + +export default function TimeDisplay({ statusSignal, end_time } : TimeDisplayProps) { + const [timeRemaining, setTimeRemaining] = useState(0); + + useEffect(() => { + function updateStatus(s : string) { + statusSignal(s); + } + + const getTimeRemaining = setInterval(() => { + const [endHours, endMins, endSec] = end_time + .split(":") + .map(Number); + + const d = new Date(); + const end_time_serial = endHours * 60 * 60 + endMins * 60 + endSec; + const cur_time = + d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); + + const remaining_time = end_time_serial - cur_time; + if (remaining_time <= 0) { + updateStatus("finished"); + clearInterval(getTimeRemaining); + } + + setTimeRemaining(remaining_time); + }, 1000); + + return () => clearInterval(getTimeRemaining); + }, [end_time, timeRemaining]); + + useEffect(() => { + console.log("end time changed to ", end_time); + }, [end_time]) + + return ( +
+

Timer

+
+ {Timer(timeRemaining)} +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/client/src/pages/timer.tsx b/client/src/pages/focus.tsx similarity index 67% rename from client/src/pages/timer.tsx rename to client/src/pages/focus.tsx index e25af55..e6f270a 100644 --- a/client/src/pages/timer.tsx +++ b/client/src/pages/focus.tsx @@ -1,9 +1,18 @@ import React, { useState } from "react"; import CurrentTask from "@/components/ui/currentTask"; +import TimeDisplay from "@/components/ui/timeDisplay"; + +interface Task { + id: number; + start_time: string; + end_time: string; +} const CountdownTimer = () => { - const [tasks, setTasks] = useState([]); + const [tasks, setTasks] = useState([]); + const [currentTask, setCurrentTask] = useState(); + const [taskTime, setTaskTime] = useState(1000000); const [loading, setLoading] = useState(false); async function refreshTasks() { @@ -16,15 +25,46 @@ const CountdownTimer = () => { } const result = await response.json(); - console.log(result); setTasks(result); - console.log(tasks); + getCurrentTask(); setLoading(false); } catch (error) { console.error(error); } } + function getCurrentTask() { + console.log("getting current task"); + tasks.forEach((task) => { + const [startHours, startMins, startSec] = task.start_time + .split(":") + .map(Number); + const [endHours, endMins, endSec] = task.end_time + .split(":") + .map(Number); + + const d = new Date(); + const start_time = startHours * 60 * 60 + startMins * 60 + startSec; + const end_time = endHours * 60 * 60 + endMins * 60 + endSec; + const cur_time = + d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); + + if (start_time <= cur_time && end_time >= cur_time) { + if (start_time < taskTime) { + setCurrentTask(task); + setTaskTime(start_time); + } + } + }); + } + + function onTaskEnd(status : string) { + if (status == "finished") { + console.log("finished"); + getCurrentTask(); + } + } + // check for tasks // direct to make task page if no tasks // refresh timer to check for tasks @@ -73,7 +113,14 @@ const CountdownTimer = () => { )}
- + {currentTask ? ( +
+

{currentTask.end_time}

+ +
+ ):( + <> + )}
From c9dd337bcc654bb9feb33ba8251a38612216fa76 Mon Sep 17 00:00:00 2001 From: TobbleCobble Date: Sat, 13 Dec 2025 07:28:50 +0000 Subject: [PATCH 4/9] countdown display for current task --- client/src/components/ui/timeDisplay.tsx | 91 +++++++++++------------- client/src/pages/focus.tsx | 50 ++++++------- client/src/pages/index.tsx | 2 +- 3 files changed, 69 insertions(+), 74 deletions(-) diff --git a/client/src/components/ui/timeDisplay.tsx b/client/src/components/ui/timeDisplay.tsx index bbf8845..a159095 100644 --- a/client/src/components/ui/timeDisplay.tsx +++ b/client/src/components/ui/timeDisplay.tsx @@ -1,55 +1,48 @@ import React, { useEffect, useState } from "react"; -import { finished } from "stream"; + import Timer from "./timer"; interface TimeDisplayProps { - statusSignal : (data: string) => void; - end_time : string; + statusSignal: (data: string) => void; + end_time: string; } -export default function TimeDisplay({ statusSignal, end_time } : TimeDisplayProps) { - const [timeRemaining, setTimeRemaining] = useState(0); - - useEffect(() => { - function updateStatus(s : string) { - statusSignal(s); - } - - const getTimeRemaining = setInterval(() => { - const [endHours, endMins, endSec] = end_time - .split(":") - .map(Number); - - const d = new Date(); - const end_time_serial = endHours * 60 * 60 + endMins * 60 + endSec; - const cur_time = - d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); - - const remaining_time = end_time_serial - cur_time; - if (remaining_time <= 0) { - updateStatus("finished"); - clearInterval(getTimeRemaining); - } - - setTimeRemaining(remaining_time); - }, 1000); - - return () => clearInterval(getTimeRemaining); - }, [end_time, timeRemaining]); - - useEffect(() => { - console.log("end time changed to ", end_time); - }, [end_time]) - - return ( -
-

Timer

-
- {Timer(timeRemaining)} -
-
- -
-
- ); -} \ No newline at end of file +export default function TimeDisplay({ + statusSignal, + end_time, +}: TimeDisplayProps) { + const [timeRemaining, setTimeRemaining] = useState(0); + + useEffect(() => { + function updateStatus(s: string) { + statusSignal(s); + } + + const getTimeRemaining = setInterval(() => { + const [endHours, endMins, endSec] = end_time.split(":").map(Number); + + const d = new Date(); + const end_time_serial = endHours * 60 * 60 + endMins * 60 + endSec; + const cur_time = + d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); + + const remaining_time = end_time_serial - cur_time; + if (remaining_time <= 1) { + updateStatus("finished"); + clearInterval(getTimeRemaining); + } + + setTimeRemaining(remaining_time); + }, 1000); + + return () => clearInterval(getTimeRemaining); + }, [end_time, timeRemaining, statusSignal]); + + return ( +
+

Timer

+
{Timer(timeRemaining)}
+
+
+ ); +} diff --git a/client/src/pages/focus.tsx b/client/src/pages/focus.tsx index e6f270a..5d0d635 100644 --- a/client/src/pages/focus.tsx +++ b/client/src/pages/focus.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; -import CurrentTask from "@/components/ui/currentTask"; import TimeDisplay from "@/components/ui/timeDisplay"; interface Task { @@ -12,7 +11,6 @@ interface Task { const CountdownTimer = () => { const [tasks, setTasks] = useState([]); const [currentTask, setCurrentTask] = useState(); - const [taskTime, setTaskTime] = useState(1000000); const [loading, setLoading] = useState(false); async function refreshTasks() { @@ -35,30 +33,31 @@ const CountdownTimer = () => { function getCurrentTask() { console.log("getting current task"); + let task_time = 1000000; + tasks.forEach((task) => { - const [startHours, startMins, startSec] = task.start_time - .split(":") - .map(Number); - const [endHours, endMins, endSec] = task.end_time - .split(":") - .map(Number); - - const d = new Date(); - const start_time = startHours * 60 * 60 + startMins * 60 + startSec; - const end_time = endHours * 60 * 60 + endMins * 60 + endSec; - const cur_time = - d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); - - if (start_time <= cur_time && end_time >= cur_time) { - if (start_time < taskTime) { - setCurrentTask(task); - setTaskTime(start_time); - } + const [startHours, startMins, startSec] = task.start_time + .split(":") + .map(Number); + const [endHours, endMins, endSec] = task.end_time.split(":").map(Number); + + const d = new Date(); + const start_time = startHours * 60 * 60 + startMins * 60 + startSec; + const end_time = endHours * 60 * 60 + endMins * 60 + endSec; + const cur_time = + d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); + + if (start_time <= cur_time && end_time >= cur_time) { + if (start_time < task_time) { + console.log("new time", start_time); + setCurrentTask(task); + task_time = start_time; } + } }); } - function onTaskEnd(status : string) { + function onTaskEnd(status: string) { if (status == "finished") { console.log("finished"); getCurrentTask(); @@ -115,10 +114,13 @@ const CountdownTimer = () => {
{currentTask ? (
-

{currentTask.end_time}

- +

{currentTask.end_time}

+
- ):( + ) : ( <> )}
diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index c051281..df27d53 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -24,7 +24,7 @@ export default function Home() { fontSans.variable, )} > -

Test title

+

wTest title

From 2b4b06dbcc588fa35c8e1f9efc99c3afcf65af5d Mon Sep 17 00:00:00 2001 From: TobbleCobble Date: Tue, 16 Dec 2025 05:11:44 +0000 Subject: [PATCH 5/9] shows countdown to next taks if none current --- client/src/components/ui/taskDisplay.tsx | 12 ++ client/src/components/ui/timeDisplay.tsx | 41 ++++--- client/src/components/ui/timer.tsx | 12 +- client/src/pages/focus.tsx | 149 ++++++++++++++++------- client/src/styles/globals.css | 2 + client/tailwind.config.ts | 1 + 6 files changed, 158 insertions(+), 59 deletions(-) create mode 100644 client/src/components/ui/taskDisplay.tsx diff --git a/client/src/components/ui/taskDisplay.tsx b/client/src/components/ui/taskDisplay.tsx new file mode 100644 index 0000000..4ccc74e --- /dev/null +++ b/client/src/components/ui/taskDisplay.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +export default function TaskDisplay(task_name: string) { + return ( +
+

Current Focus

+
+ {task_name} +
+
+ ); +} diff --git a/client/src/components/ui/timeDisplay.tsx b/client/src/components/ui/timeDisplay.tsx index a159095..965ffd9 100644 --- a/client/src/components/ui/timeDisplay.tsx +++ b/client/src/components/ui/timeDisplay.tsx @@ -4,31 +4,30 @@ import Timer from "./timer"; interface TimeDisplayProps { statusSignal: (data: string) => void; - end_time: string; + time: string; + current: boolean; } export default function TimeDisplay({ statusSignal, - end_time, + time, + current, }: TimeDisplayProps) { const [timeRemaining, setTimeRemaining] = useState(0); useEffect(() => { - function updateStatus(s: string) { - statusSignal(s); - } - const getTimeRemaining = setInterval(() => { - const [endHours, endMins, endSec] = end_time.split(":").map(Number); + const [Hours, Mins, Sec] = time.split(":").map(Number); const d = new Date(); - const end_time_serial = endHours * 60 * 60 + endMins * 60 + endSec; + const time_serial = Hours * 60 * 60 + Mins * 60 + Sec; const cur_time = d.getHours() * 60 * 60 + d.getMinutes() * 60 + d.getSeconds(); - const remaining_time = end_time_serial - cur_time; + let remaining_time = 0; + + remaining_time = time_serial - cur_time; if (remaining_time <= 1) { - updateStatus("finished"); clearInterval(getTimeRemaining); } @@ -36,12 +35,26 @@ export default function TimeDisplay({ }, 1000); return () => clearInterval(getTimeRemaining); - }, [end_time, timeRemaining, statusSignal]); + }, [time, timeRemaining]); + + useEffect(() => { + if (timeRemaining <= 1) { + statusSignal("finished"); + } + }, [timeRemaining, statusSignal]); return ( -
-

Timer

-
{Timer(timeRemaining)}
+
+ {current ? ( + <> +

Timer

+ + ) : ( + <> +

Next Task

+ + )} +
{Timer(timeRemaining)}
); diff --git a/client/src/components/ui/timer.tsx b/client/src/components/ui/timer.tsx index 06eabda..353ac7a 100644 --- a/client/src/components/ui/timer.tsx +++ b/client/src/components/ui/timer.tsx @@ -7,8 +7,14 @@ const Timer = (timeRemaining: number) => { return (
- {hours.toString().padStart(2, "0")} - : + {hours > 0 ? ( + <> + {hours.toString()} + : + + ) : ( + <> + )} {minutes.toString().padStart(2, "0")} : {seconds.toString().padStart(2, "0")} @@ -18,7 +24,7 @@ const Timer = (timeRemaining: number) => { }; return ( -
+
{formatTime(timeRemaining)}
); diff --git a/client/src/pages/focus.tsx b/client/src/pages/focus.tsx index 5d0d635..5651d87 100644 --- a/client/src/pages/focus.tsx +++ b/client/src/pages/focus.tsx @@ -1,19 +1,37 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; +import TaskDisplay from "@/components/ui/taskDisplay"; import TimeDisplay from "@/components/ui/timeDisplay"; -interface Task { +interface Time { id: number; + day: number; start_time: string; end_time: string; + repeating: boolean; + task: number; +} + +interface Task { + id: number; + name: string; +} + +function serializeTime(time: string) { + const [Hours, Mins, Sec] = time.split(":").map(Number); + + return Hours * 60 * 60 + Mins * 60 + Sec; } const CountdownTimer = () => { + const [times, setTimes] = useState([]); const [tasks, setTasks] = useState([]); - const [currentTask, setCurrentTask] = useState(); + const [currentTime, setCurrentTime] = useState