From 8460a5bfe726ab4add27a60a4048b3d96cca583d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przy=C5=82uski?= Date: Thu, 3 Oct 2024 13:05:22 +0200 Subject: [PATCH 01/38] feat: introduce add todo logic --- package-lock.json | 9 ++++---- package.json | 2 +- src/App.tsx | 59 +++++++++++++++++++++++++++++++++++++++++++++-- src/index.tsx | 6 ++--- src/types/Todo.ts | 5 ++++ 5 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 src/types/Todo.ts diff --git a/package-lock.json b/package-lock.json index 0adcc869f..b2887aa61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", @@ -1170,10 +1170,11 @@ } }, "node_modules/@mate-academy/scripts": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.8.5.tgz", - "integrity": "sha512-mHRY2FkuoYCf5U0ahIukkaRo5LSZsxrTSgMJheFoyf3VXsTvfM9OfWcZIDIDB521kdPrScHHnRp+JRNjCfUO5A==", + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.9.12.tgz", + "integrity": "sha512-/OcmxMa34lYLFlGx7Ig926W1U1qjrnXbjFJ2TzUcDaLmED+A5se652NcWwGOidXRuMAOYLPU2jNYBEkKyXrFJA==", "dev": true, + "license": "MIT", "dependencies": { "@octokit/rest": "^17.11.2", "@types/get-port": "^4.2.0", diff --git a/package.json b/package.json index e6134ce84..91d7489b9 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@cypress/react18": "^2.0.1", - "@mate-academy/scripts": "^1.8.5", + "@mate-academy/scripts": "^1.9.12", "@mate-academy/students-ts-config": "*", "@mate-academy/stylelint-config": "*", "@types/node": "^20.14.10", diff --git a/src/App.tsx b/src/App.tsx index a399287bd..7e45bddf5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,26 @@ /* eslint-disable jsx-a11y/control-has-associated-label */ -import React from 'react'; +import React, { useState } from 'react'; +import { Todo } from './types/Todo'; export const App: React.FC = () => { + const [todos, setTodos] = useState([]); + const [todoTitle, setTodoTitle] = useState(''); + + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + + if (todoTitle.trim()) { + const newTodo: Todo = { + id: +new Date(), + title: todoTitle, + completed: false, + }; + + setTodos([...todos, newTodo]); + setTodoTitle(''); + } + }; + return (

todos

@@ -16,19 +35,52 @@ export const App: React.FC = () => { /> {/* Add a todo on form submit */} -
+ setTodoTitle(event.target.value)} />
{/* This is a completed todo */} + {todos.map(todo => ( +
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} + + + + {todo.title} + + {/* Remove button appears only on hover */} + +
+ ))}
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
); }; From 3ceeb56d081991e22ce2bd702312dc57ee740ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przy=C5=82uski?= Date: Sun, 6 Oct 2024 10:24:18 +0200 Subject: [PATCH 13/38] feat: focus headerInput if click outside renaming todo --- src/components/Header/Header.tsx | 5 ++--- src/components/Todos/Todos.tsx | 19 +++++++++++++++++-- src/components/context/TodoContext.tsx | 5 ++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index b157d26f9..0687924be 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -1,10 +1,9 @@ -import { useRef, useState } from 'react'; +import { useState } from 'react'; import { useTodoContext } from '../context/TodoContext'; export const Header = () => { const [todoTitle, setTodoTitle] = useState(''); - const { addTodo } = useTodoContext(); - const headerInputRef = useRef(null); + const { addTodo, headerInputRef } = useTodoContext(); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); diff --git a/src/components/Todos/Todos.tsx b/src/components/Todos/Todos.tsx index c6bf9bb17..24d83c6fa 100644 --- a/src/components/Todos/Todos.tsx +++ b/src/components/Todos/Todos.tsx @@ -5,8 +5,13 @@ export const Todos = () => { const [editingTodoId, setEditingTodoId] = useState(null); const [editingTitle, setEditingTitle] = useState(''); const renameInputRef = useRef(null); - const { todos, toggleTodoStatus, updateTodoTitle, deleteTodo } = - useTodoContext(); + const { + todos, + toggleTodoStatus, + updateTodoTitle, + deleteTodo, + headerInputRef, + } = useTodoContext(); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); @@ -20,6 +25,10 @@ export const Todos = () => { } setEditingTodoId(null); + + if (headerInputRef.current) { + headerInputRef.current.focus(); + } }; const handleDoubleClick = (id: number, currentTitle: string) => { @@ -45,6 +54,12 @@ export const Todos = () => { } setEditingTodoId(null); + + setTimeout(() => { + if (headerInputRef.current) { + headerInputRef.current.focus(); + } + }, 0); } }; diff --git a/src/components/context/TodoContext.tsx b/src/components/context/TodoContext.tsx index 9ac57a831..c1315aa81 100644 --- a/src/components/context/TodoContext.tsx +++ b/src/components/context/TodoContext.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useState } from 'react'; +import { createContext, useContext, useRef, useState } from 'react'; import { Todo } from '../../types/Todo'; type TodoContextProps = { @@ -7,6 +7,7 @@ type TodoContextProps = { toggleTodoStatus: (id: number) => void; updateTodoTitle: (id: number, title: string) => void; deleteTodo: (id: number) => void; + headerInputRef: React.RefObject; }; const TodoContext = createContext(undefined); @@ -29,6 +30,7 @@ export const TodoProvider = ({ children }: TodoProviderProps) => { return storedTodos ? JSON.parse(storedTodos) : []; }); + const headerInputRef = useRef(null); const addTodo = (title: string) => { const newTodo: Todo = { @@ -86,6 +88,7 @@ export const TodoProvider = ({ children }: TodoProviderProps) => { toggleTodoStatus, updateTodoTitle, deleteTodo, + headerInputRef, }; return {children}; From 310a9a14c9f9002a51b689afc69f12fb1759dc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przy=C5=82uski?= Date: Sun, 6 Oct 2024 11:01:10 +0200 Subject: [PATCH 14/38] feat: add filter change onClick in Footer --- src/components/Footer/Footer.tsx | 11 +++++++---- src/components/context/TodoContext.tsx | 19 +++++++++++++++++++ src/types/Filter.ts | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/types/Filter.ts diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx index 682f383b0..01bcfbabe 100644 --- a/src/components/Footer/Footer.tsx +++ b/src/components/Footer/Footer.tsx @@ -1,7 +1,7 @@ import { useTodoContext } from '../context/TodoContext'; export const Footer = () => { - const { todos } = useTodoContext(); + const { todos, filter, setFilter } = useTodoContext(); const incompleteTodos = todos.filter(todo => todo.completed === false).length; @@ -18,24 +18,27 @@ export const Footer = () => {
))} From a00ba3f322a9a7bda5f6190bdb7007eceb5077cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przy=C5=82uski?= Date: Tue, 8 Oct 2024 06:59:22 +0200 Subject: [PATCH 26/38] refactor: remove inline styles and aplly them with scss --- src/components/Todos/Todos.tsx | 3 +-- src/styles/todo.scss | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Todos/Todos.tsx b/src/components/Todos/Todos.tsx index e594e6c88..5a5db5410 100644 --- a/src/components/Todos/Todos.tsx +++ b/src/components/Todos/Todos.tsx @@ -103,9 +103,8 @@ export const Todos = () => { {/* This form is shown instead of the title and remove button */} -
+ Date: Tue, 8 Oct 2024 07:08:15 +0200 Subject: [PATCH 27/38] refactor: destructure todo in Todos and TodoItem --- src/components/TodoItem/TodoItem.tsx | 16 ++++++++-------- src/components/Todos/Todos.tsx | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/components/TodoItem/TodoItem.tsx b/src/components/TodoItem/TodoItem.tsx index c10ca1de8..46a36803d 100644 --- a/src/components/TodoItem/TodoItem.tsx +++ b/src/components/TodoItem/TodoItem.tsx @@ -8,7 +8,7 @@ type Props = { }; export const TodoItem = ({ - todo, + todo: { id, title, completed }, toggleTodoStatus, deleteTodo, handleDoubleClick, @@ -16,30 +16,30 @@ export const TodoItem = ({ return ( <> {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */} -