diff --git a/src/App.css b/src/App.css index 4c4f081..2a524e1 100644 --- a/src/App.css +++ b/src/App.css @@ -1,11 +1,56 @@ button { - padding: 0 2%; - font-size: 2vw; + border: 1px solid rgb(79, 79, 79); + border-radius: 5px; + padding: 1%; + white-space: nowrap; cursor: pointer; } +.bigBtn { + font-size: 2vw; +} + +.midBtn { + font-size: 1.2vw; +} + +.input { + width: 100%; + padding: 1%; + border: 1px solid red; + border-radius: 5px; + outline: none; + color: white; + background-color: black; +} + +.sub-container { + width: 100%; + border: 1px solid red; + border-radius: 10px; + padding: 10px; + display: flex; + flex-direction: column; + row-gap: 12px; +} + +.counter-stats { + font-size: 24px; + font-weight: 700; +} + +.ul { + width: 95%; + align-self: flex-end; +} + +.li { + padding: 5px 0; + font-size: 0.8rem; +} + .hide { - display: none; + display: none !important; } li { @@ -23,12 +68,15 @@ li { .Todos, .Doing, .Done { - width: 33%; + width: 100%; border: 1px solid red; - border-radius: 15px; + border-radius: 20px; + padding: 5px; display: flex; flex-direction: column; + row-gap: 1%; align-items: center; + overflow-y: auto; } @media (width <= 720px) { @@ -41,6 +89,7 @@ li { .Doing, .Done { width: 100%; + overflow-y: visible; } .Todos { diff --git a/src/doing/Doing.css b/src/doing/Doing.css index 1acb9a9..0afc9c3 100644 --- a/src/doing/Doing.css +++ b/src/doing/Doing.css @@ -1,19 +1,9 @@ -.Doing { - padding: 5px; - row-gap: 100px; -} - -.pomodoro { - width: 100%; - padding: 5px; - display: flex; - flex-direction: column; - justify-content: center; +.Doing .pomodoro { align-items: center; row-gap: 50px; } -.clock { +.Doing .clock { width: fit-content; border: 1px solid red; border-radius: 20px; @@ -23,24 +13,24 @@ font-family: 'CustomFont', monospace; } -.controls { +.Doing .controls { width: 100%; justify-content: center; display: flex; column-gap: 10px; } -.motivational { +.Doing .motivational { cursor: pointer; display: flex; flex-direction: column; row-gap: 10px; } -.motivational p:first-of-type { +.Doing .motivational p:first-of-type { font-style: italic; } -.motivational p:last-of-type { +.Doing .motivational p:last-of-type { font-size: 0.7rem; } diff --git a/src/doing/Doing.jsx b/src/doing/Doing.jsx index fcf1639..aca66a1 100644 --- a/src/doing/Doing.jsx +++ b/src/doing/Doing.jsx @@ -71,7 +71,7 @@ export const Doing = () => { return (

Doing

-
+
{ />
- - - + + +

{quote}

diff --git a/src/done/Done.css b/src/done/Done.css index 20ebaf5..9b6962a 100644 --- a/src/done/Done.css +++ b/src/done/Done.css @@ -1,3 +1,49 @@ -.Done { - color: white; +.Done h2 { + text-align: right; +} + +.Done .worked-hours .this { + width: 100%; + display: flex; + justify-content: space-evenly; +} + +.Done .worked-hours .this .this-month, +.Done .worked-hours .this .this-week, +.Done .worked-hours .this .this-day { + display: flex; + flex-direction: column; + align-items: center; +} + +.Done .worked-hours .this .this-month span:last-of-type, +.Done .worked-hours .this .this-week span:last-of-type, +.Done .worked-hours .this .this-day span:last-of-type { + white-space: nowrap; + font-size: 0.8rem; +} + +.Done .completed-tasks.sub-container ul li.dones { + color: gray; +} + +.Done .completed-tasks.sub-container .modal { + display: flex; + flex-direction: column; + row-gap: 10px; +} + +.Done .completed-tasks.sub-container .modal p { + color: red; +} + +.Done .completed-tasks.sub-container .options { + display: flex; + justify-content: space-around; +} + +.Done .completed-tasks.sub-container footer { + width: 100%; + display: flex; + column-gap: 12px; } diff --git a/src/done/Done.jsx b/src/done/Done.jsx index 2f431d7..680d6e0 100644 --- a/src/done/Done.jsx +++ b/src/done/Done.jsx @@ -1,9 +1,51 @@ +import { useState, useEffect } from 'react' +import { Store } from '../store/store' import './Done.css' export const Done = () => { + const store = Store() + const [input, setInput] = useState("") + const [showModal, setShowModal] = useState("hide") + const [showFooter, setShowFooter] = useState("") + const handleInputEnterKey = k => k.key === "Enter" && input.trim() != "" && (store.tasks.add(input), setInput("")) + useEffect(() => localStorage.setItem("Completed Tasks", JSON.stringify(store.tasks.completed)), [store.tasks.completed]) + useEffect(() => localStorage.setItem("Worked Hours History", JSON.stringify(store.tasks.workedHoursHistory)), [store.tasks.workedHoursHistory]) + return (

Done

+
+

Worked Hours

+
+
{store.tasks.workedHours().month}Last Month
+
{store.tasks.workedHours().week}Last Week
+
{store.tasks.workedHours().day}Today
+
+
+
+

Completed Tasks

+
    + {store.tasks.completed.map(item => (
  • {item.content}
  • ))} +
+
+

Deleting all completed tasks will log today's work and start a new day. Are you sure?

+
+ + +
+
+
+ + setInput(e.target.value)} + onKeyDown={k => handleInputEnterKey(k)} + /> +
+
) } \ No newline at end of file diff --git a/src/store/store.js b/src/store/store.js index d8308fd..ec9eebc 100644 --- a/src/store/store.js +++ b/src/store/store.js @@ -1,42 +1,52 @@ import { create } from "zustand" import { devtools } from "zustand/middleware" import { add, completed, markAsDone, markAsTodo, deleteDones } from "./todo_logic.js" +import { addCompletedTask, deleteAllCompletedTasks, workedHours } from './tasks_logic.js' const todoDailySlice = (set, get) => ({ title: "Daily Goals", - completed: () => completed(get, "daily"), todos: JSON.parse(localStorage.getItem("Daily Goals Todos")) || [], dones: JSON.parse(localStorage.getItem("Daily Goals Dones")) || [], - add: (input) => add(set, input, "daily"), - markAsDone: (item) => markAsDone(set, item, "daily"), - markAsTodo: (item) => markAsTodo(set, item, "daily"), + completed: () => completed(get, "daily"), + add: input => add(set, input, "daily"), + markAsDone: item => markAsDone(set, item, "daily"), + markAsTodo: item => markAsTodo(set, item, "daily"), deleteDones: () => deleteDones(set, "daily") }) const todoWeeklySlice = (set, get) => ({ title: "Weekly Goals", - completed: () => completed(get, "weekly"), todos: JSON.parse(localStorage.getItem("Weekly Goals Todos")) || [], dones: JSON.parse(localStorage.getItem("Weekly Goals Dones")) || [], - add: (input) => add(set, input, "weekly"), - markAsDone: (item) => markAsDone(set, item, "weekly"), - markAsTodo: (item) => markAsTodo(set, item, "weekly"), + completed: () => completed(get, "weekly"), + add: input => add(set, input, "weekly"), + markAsDone: item => markAsDone(set, item, "weekly"), + markAsTodo: item => markAsTodo(set, item, "weekly"), deleteDones: () => deleteDones(set, "weekly") }) const todoMonthlySlice = (set, get) => ({ title: "Monthly Goals", - completed: () => completed(get, "monthly"), todos: JSON.parse(localStorage.getItem("Monthly Goals Todos")) || [], dones: JSON.parse(localStorage.getItem("Monthly Goals Dones")) || [], - add: (input) => add(set, input, "monthly"), - markAsDone: (item) => markAsDone(set, item, "monthly"), - markAsTodo: (item) => markAsTodo(set, item, "monthly"), + completed: () => completed(get, "monthly"), + add: input => add(set, input, "monthly"), + markAsDone: item => markAsDone(set, item, "monthly"), + markAsTodo: item => markAsTodo(set, item, "monthly"), deleteDones: () => deleteDones(set, "monthly") }) +const tasksSlice = (set, get) => ({ + completed: JSON.parse(localStorage.getItem("Completed Tasks")) || [], + workedHoursHistory: JSON.parse(localStorage.getItem("Worked Hours History")) || [], + add: input => addCompletedTask(set, input), + deleteCompleted: () => deleteAllCompletedTasks(set, get), + workedHours: () => workedHours(get), +}) + export const Store = create(devtools((set, get) => ({ daily: todoDailySlice(set, get), weekly: todoWeeklySlice(set, get), - monthly: todoMonthlySlice(set, get) + monthly: todoMonthlySlice(set, get), + tasks: tasksSlice(set, get) }))) \ No newline at end of file diff --git a/src/store/tasks_logic.js b/src/store/tasks_logic.js new file mode 100644 index 0000000..80a89d7 --- /dev/null +++ b/src/store/tasks_logic.js @@ -0,0 +1,25 @@ +export const addCompletedTask = (set, input) => set(state => ({ + tasks: { + ...state.tasks, + completed: [...state.tasks.completed, { id: Date.now(), content: input }] + } +}), false, 'tasks/add') + +export const deleteAllCompletedTasks = (set, get) => set(state => { + const workedHoursHistoryArray = [get().tasks.completed.length * 15 / 60, ...state.tasks.workedHoursHistory] + workedHoursHistoryArray.length > 30 && workedHoursHistoryArray.pop() + return ({ + tasks: { + ...state.tasks, + workedHoursHistory: workedHoursHistoryArray, + completed: [] + } + }) +}, false, 'tasks/deleteAllCompleted') + +export const workedHours = get => { + const day = get().tasks.completed.length * 15 / 60 + const week = get().tasks.workedHoursHistory.slice(0, 7).reduce((a, b) => a + b, 0) + const month = get().tasks.workedHoursHistory.reduce((a, b) => a + b, 0) + return ({ "day": day, "week": week, "month": month }) +} diff --git a/src/todo/Todo.css b/src/todo/Todo.css index 72ae026..d3effc6 100644 --- a/src/todo/Todo.css +++ b/src/todo/Todo.css @@ -1,37 +1,15 @@ -.Todo { - width: 100%; - border: 1px solid red; - border-radius: 10px; - padding: 10px; - display: flex; - flex-direction: column; - row-gap: 12px; -} - .Todo header { display: flex; justify-content: space-between; align-items: center; } -.Todo header span span { - font-size: 24px; - font-weight: 700; -} - .Todo header h1 { font-size: 22px; } -.Todo ul { - width: 95%; - align-self: flex-end; - font-size: 12px; -} - .Todo ul li { cursor: pointer; - padding: 5px 0; } .Todo ul .dones { @@ -42,19 +20,3 @@ display: flex; column-gap: 12px; } - -.Todo footer button { - width: fit-content; - font-size: 14px; - white-space: nowrap; -} - -.Todo footer input { - width: 100%; - padding: 5px; - border: 1px solid red; - border-radius: 5px; - outline: none; - color: white; - background-color: black; -} diff --git a/src/todo/Todo.jsx b/src/todo/Todo.jsx index b43e521..a57f0da 100644 --- a/src/todo/Todo.jsx +++ b/src/todo/Todo.jsx @@ -12,23 +12,24 @@ export const Todo = ({ store }) => { }, [store.todos, store.dones, store.title]) return ( -
+
-
Completed: {store.completed()}
+
Completed: {store.completed()}

{store.title}

-
    - {store.todos.map(item => (
  • store.markAsDone(item)}>{item.content}
  • ))} - {store.dones.map(item => (
  • store.markAsTodo(item)}>{item.content}
  • ))} +
      + {store.todos.map(item => (
    • store.markAsDone(item)}>{item.content}
    • ))} + {store.dones.map(item => (
    • store.markAsTodo(item)}>{item.content}
    • ))}
diff --git a/src/todo/Todos.css b/src/todo/Todos.css deleted file mode 100644 index 3a232b3..0000000 --- a/src/todo/Todos.css +++ /dev/null @@ -1,5 +0,0 @@ -.Todos { - display: flex; - row-gap: 1%; - overflow-y: auto; -} diff --git a/src/todo/Todos.jsx b/src/todo/Todos.jsx index 4527f46..8419032 100644 --- a/src/todo/Todos.jsx +++ b/src/todo/Todos.jsx @@ -1,6 +1,5 @@ import { Store } from '../store/store.js' import { Todo } from './Todo.jsx' -import './Todos.css' export const Todos = () => { const store = Store()