Skip to content

Commit

Permalink
Merge pull request #4 from danifromecuador/feat/todo
Browse files Browse the repository at this point in the history
feat/todo
  • Loading branch information
danifromecuador authored Aug 26, 2024
2 parents a19898c + 8d1cfe1 commit af5c1bf
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 33 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"axios": "^1.7.3",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-countdown": "^2.3.5",
"react-dom": "^18.3.1",
Expand Down
14 changes: 12 additions & 2 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ button {
display: none;
}

li {
list-style: none;
}

.App {
width: 98vw;
height: 95vh;
Expand All @@ -16,7 +20,7 @@ button {
column-gap: 1%;
}

.Todo,
.Todos,
.Doing,
.Done {
width: 33%;
Expand All @@ -33,12 +37,18 @@ button {
row-gap: 1%;
}

.Todo,
.Todos,
.Doing,
.Done {
width: 100%;
}

.Todos {
overflow-y: visible;
flex-direction: column;
row-gap: 10px;
}

.clock {
font-size: 16vw;
}
Expand Down
28 changes: 10 additions & 18 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
// import { Store } from './store/store.js'
import {Todo} from './todo/Todo.jsx'
import {Doing} from './doing/Doing.jsx'
import {Done} from './done/Done.jsx'
import { Todos } from './todo/Todos.jsx'
import { Doing } from './doing/Doing.jsx'
import { Done } from './done/Done.jsx'
import './App.css'

export const App = () => {
// const store = Store()
return (
<div className='App'>
{/* <h1>App Component</h1>
<div>Bears: {store.bears.amount}</div>
<div>Cows: {store.cows.amount}</div>
<button onClick={()=>store.bears.add()}>Add bear</button> */}
<Todo />
<Doing />
<Done />
</div>
)
}
export const App = () => (
<div className='App'>
<Todos />
<Doing />
<Done />
</div>
)
44 changes: 34 additions & 10 deletions src/store/store.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
import { create } from "zustand"
import { devtools } from "zustand/middleware"
import { add, completed, markAsDone, markAsTodo, deleteDones } from "./todo_logic.js"

const createBearSlice = set => ({
amount: 42,
add: () => set(state => ({
bears: { ...state.bears, amount: state.bears.amount + 1 }
}))
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"),
deleteDones: () => deleteDones(set, "daily")
})

const createCowSlice = () => ({
amount: 21
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"),
deleteDones: () => deleteDones(set, "weekly")
})

export const Store = create(devtools(set => ({
bears: createBearSlice(set),
cows: createCowSlice()
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"),
deleteDones: () => deleteDones(set, "monthly")
})

export const Store = create(devtools((set, get) => ({
daily: todoDailySlice(set, get),
weekly: todoWeeklySlice(set, get),
monthly: todoMonthlySlice(set, get)
})))
33 changes: 33 additions & 0 deletions src/store/todo_logic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export const add = (set, input, sliceID) => set((state) => ({
[sliceID]: {
...state[sliceID],
todos: [...state[sliceID].todos, { id: Date.now(), content: input }]
}
}), false, 'todo/add')

export const markAsDone = (set, item, sliceID) => set((state) => ({
[sliceID]: {
...state[sliceID],
todos: state[sliceID].todos.filter(i => i.id !== item.id),
dones: [...state[sliceID].dones, item].sort((a, b) => a.id - b.id)
}
}), false, 'todo/markAsDone')

export const markAsTodo = (set, item, sliceID) => set((state) => ({
[sliceID]: {
...state[sliceID],
todos: [...state[sliceID].todos, item].sort((a, b) => a.id - b.id),
dones: state[sliceID].dones.filter(i => i.id !== item.id)
}
}), false, 'todo/markAsTodo')

export const completed = (get, sliceID) => (
`${(Math.floor((get()[sliceID].dones.length / (get()[sliceID].todos.length + get()[sliceID].dones.length))*100)).toString()}%`
)

export const deleteDones = (set, sliceID) => set((state)=>({
[sliceID]: {
...state[sliceID],
dones: []
}
}), false, 'todo/deleteDones')
57 changes: 57 additions & 0 deletions src/todo/Todo.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,60 @@
.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 {
color: rgb(101, 101, 101);
}

.Todo footer {
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;
}
35 changes: 32 additions & 3 deletions src/todo/Todo.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import './Todo.css'

export const Todo = () => {
export const Todo = ({ store }) => {
const [input, setInput] = useState("")
const handleInputEnterKey = k => k.key === "Enter" && input.trim() != "" && (store.add(input), setInput(""))

useEffect(() => {
localStorage.setItem(`${store.title} Todos`, JSON.stringify(store.todos))
localStorage.setItem(`${store.title} Dones`, JSON.stringify(store.dones))
}, [store.todos, store.dones, store.title])

return (
<div className='Todo'>
<h1>Todo</h1>
<header>
<div><span className={store.completed() === "NaN%" ? 'hide' : ''}>Completed: <span>{store.completed()}</span></span></div>
<h1>{store.title}</h1>
</header>
<ul>
{store.todos.map(item => (<li key={item.id} onClick={() => store.markAsDone(item)}>{item.content}</li>))}
{store.dones.map(item => (<li key={item.id} className='dones' onClick={() => store.markAsTodo(item)}>{item.content}</li>))}
</ul>
<footer>
<button onClick={() => store.deleteDones()} className={`${store.dones.length === 0 ? 'hide' : ''}`}>Delete All Completed</button>
<input
type="text"
value={input}
placeholder="Type a goal and press Enter"
onChange={(e) => setInput(e.target.value)}
onKeyDown={(k) => handleInputEnterKey(k)}
/>
</footer>
</div>
)
}
}

Todo.propTypes = { store: PropTypes.object }
5 changes: 5 additions & 0 deletions src/todo/Todos.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.Todos {
display: flex;
row-gap: 1%;
overflow-y: auto;
}
15 changes: 15 additions & 0 deletions src/todo/Todos.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Store } from '../store/store.js'
import { Todo } from './Todo.jsx'
import './Todos.css'

export const Todos = () => {
const store = Store()
return (
<div className='Todos'>
<h1>Todo</h1>
<Todo store={store.daily} />
<Todo store={store.weekly} />
<Todo store={store.monthly} />
</div>
)
}

0 comments on commit af5c1bf

Please sign in to comment.