Skip to content

Commit

Permalink
Merge pull request #1522 from vinaybadgujar102/focus_mode
Browse files Browse the repository at this point in the history
Focus mode
  • Loading branch information
tijlleenders authored Oct 1, 2023
2 parents eff6729 + a094f9b commit 30fadc9
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 12 deletions.
5 changes: 3 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ const App = () => {
message: `${showToast.message}`,
description: <Context.Consumer>{() => `${showToast.extra}`}</Context.Consumer>,
placement: "top",
className: `toast-${darkModeEnabled ? "dark" : "light"} ${darkModeEnabled ? "dark" : "light"}-theme${theme[darkModeEnabled ? "dark" : "light"]
}`,
className: `toast-${darkModeEnabled ? "dark" : "light"} ${darkModeEnabled ? "dark" : "light"}-theme${
theme[darkModeEnabled ? "dark" : "light"]
}`,
});
};
useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/BottomNavbar/BottomNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const BottomNavbar = ({ title }: { title: string }) => {
title={themeSelection ? "ArrowIcon" : "JournalIcon"}
/>
{themeSelection ? <p>Next</p> : <p>{t("Journal")}</p>}
{title !== "myTime" && title !== "Inbox" && <GlobalAddBtn add={title} />}
{title !== "myTime" && title !== "Inbox" && title !== "Focus" && <GlobalAddBtn add={title} />}
</button>
</div>
</>
Expand Down
105 changes: 105 additions & 0 deletions src/components/MyTimeComponents/Focus.tsx/Focus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React, { useState, useEffect } from "react";
import { useRecoilValue } from "recoil";
import { darkModeState, currentScheduledTask, focusTaskTitle } from "@src/store";
import { Progress } from "antd";

import "./focus.scss";
import { formatTimeDisplay } from "@src/utils";

export const Focus = () => {
const darkModeStatus = useRecoilValue(darkModeState);

const [initialTime, setInitialTime] = useState(25 * 60);
const [time, setTime] = useState<number>(initialTime);
const [isTimerActive, setIsTimerActive] = useState<boolean>(false);
const [editMode, setEditMode] = useState<boolean>(false);
const [userEnteredTime, setUserEnteredTime] = useState<string>("");
const taskTitle = useRecoilValue(focusTaskTitle);
const isActiveTitle = useRecoilValue(currentScheduledTask);

useEffect(() => {
let interval;
if (isTimerActive && time > 0) {
interval = setInterval(() => {
setTime((prevTime) => prevTime - 1);
}, 1000);
} else if (!isTimerActive && time !== 0) {
clearInterval(interval!);
}
return () => clearInterval(interval!);
}, [isTimerActive, time]);

const toggle = () => {
setIsTimerActive(!isTimerActive);
};
const reset = () => {
const resetTime = initialTime;
setTime(resetTime);
setIsTimerActive(false);
};

const percentage = ((initialTime - time) / initialTime) * 100;
const { minutes, seconds } = formatTimeDisplay(time);

const handleEditClick = () => {
setEditMode(!editMode);
};

const handleSaveClick = () => {
const newTimeInSeconds = parseInt(userEnteredTime, 10) * 60;
if (!Number.isNaN(newTimeInSeconds)) {
setInitialTime(newTimeInSeconds);
setTime(newTimeInSeconds);
setEditMode(false);
} else setEditMode(false);
};

return (
<div className="focus">
<h6>{isActiveTitle === "" ? taskTitle : isActiveTitle}</h6>
<Progress
className={`progress-${darkModeStatus ? "dark" : ""}`}
size={200}
strokeColor="var(--icon-grad-2)"
trailColor={darkModeStatus ? "#7e7e7e" : "var(--secondary-background)"}
type="circle"
percent={percentage}
success={{ percent: 0, strokeColor: darkModeStatus ? "white" : "black" }}
format={() => {
if (minutes >= 1) {
return `${minutes} min`;
}
return `${seconds} sec`;
}}
/>
{editMode ? (
<div style={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
<input
className="default-input"
style={{ textAlign: "center", maxWidth: 100 }}
placeholder="minutes"
value={userEnteredTime}
onChange={(e) => setUserEnteredTime(e.target.value)}
/>
<button className="action-btn" type="button" onClick={handleSaveClick}>
Save
</button>
</div>
) : (
<div style={{ display: "flex", gap: "10px" }}>
<button className="action-btn" type="button" onClick={toggle}>
{isTimerActive ? "Pause" : "Start"}
</button>
<button className="action-btn" type="button" onClick={reset}>
Reset
</button>
{time === initialTime && !isTimerActive && (
<button className="action-btn" type="button" onClick={handleEditClick}>
Edit Time
</button>
)}
</div>
)}
</div>
);
};
54 changes: 54 additions & 0 deletions src/components/MyTimeComponents/Focus.tsx/focus.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.focus {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 20px;
gap: 25px;
}

.timer {
font-size: 2em;
color: #333;
width: 200px;
height: 200px;
border-radius: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
position: relative;

.timer-fill {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #333;
transform-origin: left center;
transform: scaleX(0); /* Initial width of 0 */
transition: transform 1s linear;
}

.timer-text {
z-index: 1;
}
}

.start-button {
margin-top: 2em;
padding: 1em 2em;
font-size: 1em;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;

&:hover {
background-color: #0056b3;
}
}
30 changes: 27 additions & 3 deletions src/components/MyTimeComponents/MyTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { v4 as uuidv4 } from "uuid";
import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { useRecoilValue, useSetRecoilState } from "recoil";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";

import archiveTune from "@assets/archive.mp3";
import forgetTune from "@assets/forget.mp3";
Expand All @@ -16,7 +16,7 @@ import { TaskItem } from "@src/models/TaskItem";
import { GoalItem } from "@src/models/GoalItem";
import { displayReschedule } from "@src/store/TaskState";
import { getHrFromDateString } from "@src/utils/SchedulerUtils";
import { darkModeState, displayToast, lastAction, openDevMode } from "@src/store";
import { darkModeState, displayToast, lastAction, openDevMode, selectedMyTimeView, focusTaskTitle } from "@src/store";
import { addTask, completeTask, forgetTask, getTaskByGoalId } from "@src/api/TasksAPI";

import "./index.scss";
Expand Down Expand Up @@ -48,6 +48,8 @@ export const MyTimeline: React.FC<MyTimelineProps> = ({ day, myTasks, taskDetail
const setShowToast = useSetRecoilState(displayToast);
const setLastAction = useSetRecoilState(lastAction);
const setOpenReschedule = useSetRecoilState(displayReschedule);
const setCurrentView = useSetRecoilState(selectedMyTimeView);
const setTaskTitle = useSetRecoilState(focusTaskTitle);

const [showScheduled, setShowScheduled] = useState(true);

Expand All @@ -57,7 +59,7 @@ export const MyTimeline: React.FC<MyTimelineProps> = ({ day, myTasks, taskDetail
setShowScheduled(!showScheduled);
};
// console.log(devMode);
const handleActionClick = async (actionName: "Skip" | "Reschedule" | "Done", task: ITask) => {
const handleActionClick = async (actionName: "Skip" | "Reschedule" | "Done" | "Focus", task: ITask) => {
if (day === "Today") {
const taskItem = await getTaskByGoalId(task.goalid);
if (!taskItem) {
Expand Down Expand Up @@ -97,6 +99,9 @@ export const MyTimeline: React.FC<MyTimelineProps> = ({ day, myTasks, taskDetail
} else if (actionName === "Skip") {
await forgetSound.play();
setLastAction("TaskSkipped");
} else if (actionName === "Focus") {
setTaskTitle(task.title);
setCurrentView("focus");
}
} else {
setShowToast({ open: true, message: "Let's focus on Today :)", extra: "" });
Expand Down Expand Up @@ -133,6 +138,21 @@ export const MyTimeline: React.FC<MyTimelineProps> = ({ day, myTasks, taskDetail
},
});
};
const currentHour = new Date().getHours();
const currentActiveTask = myTasks.scheduled.filter((task) => {
if (task.start) {
const startHour = parseInt(task.start.split("T")[1].slice(0, 2), 10);
if (startHour < currentHour) {
return false;
}
}
return true;
});
if (currentActiveTask[0] === undefined) {
setTaskTitle("No Scheduled Tasks");
} else {
setTaskTitle(currentActiveTask[0]?.title);
}
return (
<>
{myTasks.impossible.length > 0 && (
Expand Down Expand Up @@ -229,6 +249,10 @@ export const MyTimeline: React.FC<MyTimelineProps> = ({ day, myTasks, taskDetail
Done
</button>
<div />
<button type="button" onClick={() => handleActionClick("Focus", task)}>
Focus
</button>
<div />
</div>
) : null}
</button>
Expand Down
8 changes: 8 additions & 0 deletions src/override.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,11 @@
color: white !important;
}
}

/*ProgressBar*/
.progress-dark {
.ant-progress-text {
color: white!important;
}
}

15 changes: 9 additions & 6 deletions src/pages/MyTimePage/MyTimePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import React, { useState } from "react";
import { useRecoilState } from "recoil";

import { MyTimeline } from "@components/MyTimeComponents/MyTimeline";
import { Focus } from "@components/MyTimeComponents/Focus.tsx/Focus";

import { getOrdinalSuffix } from "@src/utils";
import SubHeader from "@src/common/SubHeader";
import AppLayout from "@src/layouts/AppLayout";
Expand Down Expand Up @@ -80,17 +82,17 @@ export const MyTimePage = () => {
return (
<AppLayout title="myTime">
<SubHeader
showLeftNav={currentView === "thisWeek"}
showRightNav={currentView === "today"}
title={currentView === "today" ? "Today" : "This Week"}
showLeftNav={currentView === "thisWeek" || currentView === "today"}
showRightNav={currentView === "today" || currentView === "focus"}
title={currentView === "today" ? "Today" : currentView === "thisWeek" ? "This Week" : "Focus"}
leftNav={() => {
setCurrentView("today");
setCurrentView(currentView === "thisWeek" ? "today" : "focus");
}}
rightNav={() => {
setCurrentView("thisWeek");
setCurrentView(currentView === "today" ? "thisWeek" : "today");
}}
/>
{getDayComponent("Today")}
{currentView === "today" && getDayComponent("Today")}
{currentView === "thisWeek" && getDayComponent("Tomorrow")}
{currentView === "thisWeek" &&
[...Array(6).keys()].map((i) => {
Expand All @@ -101,6 +103,7 @@ export const MyTimePage = () => {
}
return null;
})}
{currentView === "focus" && <Focus />}
<Reschedule />
</AppLayout>
);
Expand Down
10 changes: 10 additions & 0 deletions src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,14 @@ export const selectedMyTimeView = atom({
default: "today",
});

export const currentScheduledTask = atom({
key: "currentScheduledTask",
default: "",
});

export const focusTaskTitle = atom({
key: "focusTaskTitle",
default: "No Task Scheduled",
});

export { darkModeState, languageSelectionState };
7 changes: 7 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,10 @@ export const getMonthByIndex = (index: number) => {
];
return month[index];
};

export const formatTimeDisplay = (timeInSeconds: number) => {
const minutes = Math.floor(timeInSeconds / 60);
const seconds = timeInSeconds % 60;

return { minutes, seconds };
};

1 comment on commit 30fadc9

@vercel
Copy link

@vercel vercel bot commented on 30fadc9 Oct 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

zinzen – ./

zinzen-git-main-tijlleenders.vercel.app
zinzen-tijlleenders.vercel.app
zinzen.vercel.app

Please sign in to comment.