diff --git a/src/api/GoalsAPI/index.ts b/src/api/GoalsAPI/index.ts index b0cd37cae..d869fa21b 100644 --- a/src/api/GoalsAPI/index.ts +++ b/src/api/GoalsAPI/index.ts @@ -6,6 +6,8 @@ import { getInstallId } from "@src/utils"; import { IHintRequestBody } from "@src/models/HintItem"; import { sortGoalsByProps } from "../GCustomAPI"; import { deleteAvailableGoalHint, deleteHintItem, getGoalHintItem } from "../HintsAPI"; +import { deleteTasksDoneTodayByGoalId } from "../TasksDoneTodayAPI"; +import { deleteTaskHistoryItem } from "../TaskHistoryAPI"; export const addDeletedGoal = async (goal: GoalItem) => { await db @@ -173,6 +175,8 @@ export const removeChildrenGoals = async (parentGoalId: string) => { childrenGoals.forEach((goal) => { removeChildrenGoals(goal.id); removeGoal(goal); + deleteTasksDoneTodayByGoalId(goal.id); + deleteTaskHistoryItem(goal.id); }); }; @@ -315,6 +319,8 @@ export const notifyNewColabRequest = async (id: string, relId: string) => { export const removeGoalWithChildrens = async (goal: GoalItem) => { await removeChildrenGoals(goal.id); await removeGoal(goal); + await deleteTasksDoneTodayByGoalId(goal.id); + await deleteTaskHistoryItem(goal.id); if (goal.parentGoalId !== "root") { getGoal(goal.parentGoalId).then(async (parentGoal: GoalItem) => { const parentGoalSublist = parentGoal.sublist; diff --git a/src/api/DumpboxAPI/index.ts b/src/api/SchedulerOutputCache/index.ts similarity index 51% rename from src/api/DumpboxAPI/index.ts rename to src/api/SchedulerOutputCache/index.ts index 07f0a0a8d..a0ff76c10 100644 --- a/src/api/DumpboxAPI/index.ts +++ b/src/api/SchedulerOutputCache/index.ts @@ -1,22 +1,22 @@ /* eslint-disable no-param-reassign */ import { db } from "@models"; -import { DumpboxItem } from "@src/models/DumpboxItem"; +import { SchedulerOutputCacheItem } from "@src/models/SchedulerOutputCacheItem"; import { v4 as uuidv4 } from "uuid"; -export const getFromOutbox = async (key: string) => { +export const getSchedulerCachedRes = async (key: string) => { try { - const dumpbox = await db.dumpboxCollection.where("key").equals(key).toArray(); - return dumpbox[0]; + const schedulerOutputCache = await db.schedulerOutputCacheCollection.where("key").equals(key).toArray(); + return schedulerOutputCache[0]; } catch (err) { return null; } }; -export const addSchedulerRes = async (uniqueId: string, output: string) => { +export const addSchedulerResToCache = async (uniqueId: string, output: string) => { let newId; await db - .transaction("rw", db.dumpboxCollection, async () => { - newId = await db.dumpboxCollection.add({ + .transaction("rw", db.schedulerOutputCacheCollection, async () => { + newId = await db.schedulerOutputCacheCollection.add({ key: "scheduler", value: JSON.stringify({ uniqueId, @@ -32,11 +32,11 @@ export const addSchedulerRes = async (uniqueId: string, output: string) => { }; export const updateSchedulerCachedRes = async (uniqueId: string, output: string) => { - db.transaction("rw", db.dumpboxCollection, async () => { - await db.dumpboxCollection + db.transaction("rw", db.schedulerOutputCacheCollection, async () => { + await db.schedulerOutputCacheCollection .where("key") .equals("scheduler") - .modify((obj: DumpboxItem) => { + .modify((obj: SchedulerOutputCacheItem) => { obj.value = JSON.stringify({ uniqueId, output, diff --git a/src/api/TaskHistoryAPI/index.ts b/src/api/TaskHistoryAPI/index.ts new file mode 100644 index 000000000..ebb5efe34 --- /dev/null +++ b/src/api/TaskHistoryAPI/index.ts @@ -0,0 +1,22 @@ +import { db } from "@src/models"; +import { TaskHistoryEvents, TaskHistoryItem } from "@src/models/TaskHistoryItem"; +import { ITask } from "@src/Interfaces/Task"; + +export async function addTaskActionEvent(task: ITask, eventType: TaskHistoryEvents) { + if (!task) return; + + const newEvent: TaskHistoryItem = { + goalId: task.goalid, + eventType, + duration: task.duration, + scheduledStart: task.start, + scheduledEnd: task.deadline, + eventTime: new Date().toISOString(), + }; + + await db.taskHistoryCollection.add(newEvent); +} + +export async function deleteTaskHistoryItem(goalId: string) { + await db.taskHistoryCollection.where("goalId").equals(goalId).delete(); +} diff --git a/src/api/TasksAPI/index.ts b/src/api/TasksAPI/index.ts index a041cde00..9345bc46f 100644 --- a/src/api/TasksAPI/index.ts +++ b/src/api/TasksAPI/index.ts @@ -4,7 +4,6 @@ import { blockedSlotOfTask, TaskItem } from "@src/models/TaskItem"; import { GoalItem } from "@src/models/GoalItem"; import { calDays, convertDateToString, getLastDayDate } from "@src/utils"; import { convertDateToDay } from "@src/utils/SchedulerUtils"; -import { ITask } from "@src/Interfaces/Task"; import { ISchedulerInputGoal } from "@src/Interfaces/IScheduler"; import { getGoal } from "../GoalsAPI"; @@ -106,45 +105,6 @@ export const refreshTaskCollection = async () => { console.error("Error updating field:", error); } }; -export const completeTask = async (id: string, duration: number, task: ITask) => { - db.transaction("rw", db.taskCollection, async () => { - await db.taskCollection - .where("id") - .equals(id) - .modify((obj: TaskItem) => { - obj.completedToday += duration; - obj.completedTodayTimings.push({ - goalid: task.goalid, - start: task.start, - deadline: task.deadline, - }); - obj.completedTodayIds.push(task.taskid); - }); - }).catch((e) => { - console.log(e.stack || e); - }); -}; - -export const skipTask = async (id: string, period: string, task: ITask) => { - db.transaction("rw", db.taskCollection, async () => { - await db.taskCollection - .where("id") - .equals(id) - .modify((obj: TaskItem) => { - obj.skippedToday.push(period); - obj.completedTodayTimings.push({ - goalid: task.goalid, - start: task.start, - deadline: task.deadline, - }); - if (obj.skippedToday.length > 1) { - obj.skippedToday.sort((a, b) => Number(a.split("-")[0]) - Number(b.split("-")[0])); - } - }); - }).catch((e) => { - console.log(e.stack || e); - }); -}; export const getAllTasks = async () => { const allGoals = await db.taskCollection.toArray(); diff --git a/src/api/TasksDoneTodayAPI/index.ts b/src/api/TasksDoneTodayAPI/index.ts new file mode 100644 index 000000000..8d5562ed5 --- /dev/null +++ b/src/api/TasksDoneTodayAPI/index.ts @@ -0,0 +1,44 @@ +import { db } from "@src/models"; +import { TasksDoneTodayItem } from "@src/models/TasksDoneTodayItem"; + +export const addTaskDoneToday = async (completedTask: TasksDoneTodayItem) => { + try { + await db.tasksDoneTodayCollection.add(completedTask); + } catch (error) { + console.error("Error adding task:", error); + } +}; + +export const getAllTasksDoneToday = async () => { + try { + const tasks = await db.tasksDoneTodayCollection.toArray(); + return tasks; + } catch (error) { + console.error("Error fetching tasks:", error); + return []; + } +}; + +export const deleteTaskDoneToday = async (id: string) => { + try { + await db.tasksDoneTodayCollection.delete(id); + } catch (error) { + console.error("Error deleting task:", error); + } +}; + +export const deleteTasksDoneTodayByGoalId = async (goalId: string) => { + try { + await db.tasksDoneTodayCollection.where("goalId").equals(goalId).delete(); + } catch (error) { + console.error("Error deleting tasks by goalId:", error); + } +}; + +export const deleteAllTasksDoneToday = async () => { + try { + await db.tasksDoneTodayCollection.clear(); + } catch (error) { + console.error("Error clearing tasks:", error); + } +}; diff --git a/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx b/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx index 24df73de1..1b5679818 100644 --- a/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx +++ b/src/components/GoalsComponents/DisplayChangesModal/DisplayChangesModal.tsx @@ -8,7 +8,7 @@ import { ITagsChanges } from "@src/Interfaces/IDisplayChangesModal"; import { sendNewGoals } from "@src/helpers/BatchPublisher"; import { darkModeState, lastAction } from "@src/store"; import { getAllContacts } from "@src/api/ContactsAPI"; -import { sendUpdatedGoal } from "@src/helpers/PubSubController"; +import { sendUpdatedGoal } from "@src/controllers/PubSubController"; import { typeOfChange, typeOfIntent } from "@src/models/InboxItem"; import { archiveUserGoal, getGoal, removeGoalWithChildrens, updateGoal } from "@src/api/GoalsAPI"; import { deleteGoalChangesInID, getInboxItem, removeGoalInbox, removePPTFromInboxOfGoal } from "@src/api/InboxAPI"; diff --git a/src/components/MyTimeComponents/MyTimeline/MyTimeline.tsx b/src/components/MyTimeComponents/MyTimeline/MyTimeline.tsx index 3729a26a8..501a7da78 100644 --- a/src/components/MyTimeComponents/MyTimeline/MyTimeline.tsx +++ b/src/components/MyTimeComponents/MyTimeline/MyTimeline.tsx @@ -11,14 +11,16 @@ import chevronLeftIcon from "@assets/images/chevronLeft.svg"; import { ITask, TaskAction } from "@src/Interfaces/Task"; import { getGoal } from "@src/api/GoalsAPI"; -import { TaskItem } from "@src/models/TaskItem"; import { GoalItem } from "@src/models/GoalItem"; import { useTranslation } from "react-i18next"; import { displayToast, focusTaskTitle } from "@src/store"; -import { addTask, completeTask, getTaskByGoalId } from "@src/api/TasksAPI"; +import { addTask, getTaskByGoalId } from "@src/api/TasksAPI"; import "./index.scss"; import { displayReschedule } from "@src/store/TaskState"; +import { TasksDoneTodayItem } from "@src/models/TasksDoneTodayItem"; +import { addTaskActionEvent } from "@src/api/TaskHistoryAPI"; +import { completeTask } from "@src/controllers/TaskDoneTodayController"; import { GoalTiming } from "./GoalTiming"; import { TaskOptions } from "./TaskOptions"; import { updateImpossibleGoals } from "./updateImpossibleGoals"; @@ -27,21 +29,16 @@ type ImpossibleTaskId = string; interface MyTimelineProps { day: string; - taskDetails: { [goalid: string]: TaskItem }; - setTaskDetails: React.Dispatch< - React.SetStateAction<{ - [goalid: string]: TaskItem; - }> - >; myTasks: { scheduled: ITask[]; impossible: ImpossibleTaskId[]; freeHrsOfDay: number; scheduledHrs: number; }; + doneTasks: TasksDoneTodayItem[]; } -export const MyTimeline: React.FC = ({ day, myTasks, taskDetails, setTaskDetails }) => { +export const MyTimeline: React.FC = ({ day, myTasks, doneTasks }) => { const { t } = useTranslation(); const navigate = useNavigate(); const { state } = useLocation(); @@ -89,6 +86,12 @@ export const MyTimeline: React.FC = ({ day, myTasks, taskDetail navigate("/", { state: { ...state, displayFocus: true } }); }; + const handleDoneClick = async (task: ITask) => { + await completeTask(task.taskid, task.goalid, task.start, task.deadline); + await addTaskActionEvent(task, "completed"); + await doneSound.play(); + }; + const handleActionClick = async (actionName: TaskAction, task: ITask) => { if (actionName === TaskAction.Goal) { return handleOpenGoal(task.goalid); @@ -96,6 +99,12 @@ export const MyTimeline: React.FC = ({ day, myTasks, taskDetail if (actionName === TaskAction.Focus) { return handleFocusClick(task); } + if (actionName === TaskAction.Done) { + return handleDoneClick(task); + } + if (actionName === TaskAction.NotNow) { + return setOpenReschedule({ ...task }); + } if (day === "Today") { const taskItem = await getTaskByGoalId(task.goalid); if (!taskItem) { @@ -107,40 +116,12 @@ export const MyTimeline: React.FC = ({ day, myTasks, taskDetail title: task.title, completedTodayIds: [], skippedToday: [], - completedToday: actionName === TaskAction.Done ? Number(task.duration) : 0, + completedToday: 0, lastSkipped: "", - lastCompleted: actionName === TaskAction.Done ? new Date().toLocaleDateString() : "", + lastCompleted: "", hoursSpent: 0, - completedTodayTimings: - actionName === TaskAction.Done - ? [ - { - goalid: task.goalid, - start: task.start, - deadline: task.deadline, - }, - ] - : [], blockedSlots: [], }); - } else if (actionName === TaskAction.Done) { - const markDone = !!taskDetails[task.goalid]?.completedTodayIds.includes(task.taskid); - if (markDone) return null; - await completeTask(taskItem.id, Number(task.duration), task); - } else if (actionName === TaskAction.NotNow) { - setOpenReschedule(task); - } - if (actionName === TaskAction.Done) { - await doneSound.play(); - const updatedTask = await getTaskByGoalId(task.goalid); - if (updatedTask) { - setTaskDetails({ - ...taskDetails, - [task.goalid]: updatedTask, - }); - } - } else if (actionName === TaskAction.NotNow) { - setOpenReschedule({ ...task }); } } else { setShowToast({ open: true, message: "Let's focus on Today :)", extra: "" }); @@ -160,9 +141,7 @@ export const MyTimeline: React.FC = ({ day, myTasks, taskDetail const nextTask = myTasks.scheduled[index + 1]; const nextStartTime = nextTask ? nextTask.start.split("T")[1].slice(0, 2) : null; const displayEndTime = endTime !== nextStartTime; - const markDone = !!taskDetails[task.goalid]?.completedTodayTimings.find( - (ele) => ele.start === task.start && ele.deadline === task.deadline, - ); + const markDone = doneTasks.some((doneTask) => doneTask.scheduledTaskId === task.taskid); const showTaskOptions = displayOptionsIndex === task.taskid; return (
{showTasks.includes(day) && tasks[day] && tasks[day].scheduled.length > 0 && ( - + )}