From dad95a992a2964024108618b1deacb1a40aaaf29 Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Thu, 28 Jul 2022 15:35:31 +0300 Subject: [PATCH 01/12] fix small bags and code clearing --- package-lock.json | 35 +++ package.json | 4 + public/index.html | 4 +- src/App.css | 16 +- src/App.js | 46 ++-- src/components/AddToDo/AddToDo.js | 94 ++++---- src/components/AddToDo/addToDo.css | 33 +-- src/components/Calendar/Calendar.js | 247 +++++++++++++--------- src/components/Calendar/calendar.css | 48 ++--- src/components/Header/Header.js | 12 +- src/components/ListItem/ListItem.js | 195 +++++++++-------- src/components/ListItem/listitemstyle.css | 21 +- src/index.js | 14 +- 13 files changed, 427 insertions(+), 342 deletions(-) diff --git a/package-lock.json b/package-lock.json index 349d671..fcfe25e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", + "classnames": "^2.3.1", "moment": "^2.29.4", "randomcolor": "^0.6.2", "react": "^18.2.0", @@ -19,6 +20,9 @@ "react-scripts": "5.0.1", "uuid": "^8.3.2", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "prettier": "2.7.1" } }, "node_modules/@ampproject/remapping": { @@ -5443,6 +5447,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "node_modules/classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, "node_modules/clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -13536,6 +13545,21 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -20574,6 +20598,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, "clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -26229,6 +26258,12 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", diff --git a/package.json b/package.json index 140b8d8..63bea57 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", + "classnames": "^2.3.1", "moment": "^2.29.4", "randomcolor": "^0.6.2", "react": "^18.2.0", @@ -38,5 +39,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "prettier": "2.7.1" } } diff --git a/public/index.html b/public/index.html index a5b2e32..eba6c85 100644 --- a/public/index.html +++ b/public/index.html @@ -7,11 +7,11 @@ content="Web site created using create-react-app" /> React App - +
diff --git a/src/App.css b/src/App.css index 104fbe0..9128af3 100644 --- a/src/App.css +++ b/src/App.css @@ -1,22 +1,28 @@ -*, *::before, *::after { +*, +*::before, +*::after { box-sizing: border-box; } + .app { display: flex; - flex-direction:column; - font-family: 'Montserrat', sans-serif; + flex-direction: column; + font-family: "Montserrat", sans-serif; width: 100%; height: 100vh; margin: 0; - background-color: #20252B; + background-color: #20252b; color: white; } + .header .addtodo_div { flex-grow: 0; } + .draggable_fild { flex-grow: 10; } + .calendar { flex-grow: 0; -} \ No newline at end of file +} diff --git a/src/App.js b/src/App.js index b7b22f6..c2ee5a6 100644 --- a/src/App.js +++ b/src/App.js @@ -1,42 +1,32 @@ -import moment from 'moment' -import React, { useEffect, useState } from 'react' +import "./App.css"; -import Calendar from './components/Calendar/Calendar' -import AddToDo from './components/AddToDo/AddToDo' -import Header from './components/Header/Header' -import ListItem from './components/ListItem/ListItem' +import moment from "moment"; +import React, { useEffect, useState } from 'react'; -import './App.css' +import Calendar from "./components/Calendar/Calendar"; +import AddToDo from "./components/AddToDo/AddToDo"; +import Header from "./components/Header/Header"; +import ListItem from "./components/ListItem/ListItem"; function App() { - - const [todo,setToDo] = useState( - JSON.parse(localStorage.getItem('items')) || {} - - ) + const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}); useEffect(() => { - localStorage.setItem('items',JSON.stringify(todo)) - }, [todo]) - - const [selectedDay, setSelectedDay] = useState(moment()) - - - + localStorage.setItem("items", JSON.stringify(todo)); + }, [todo]); + const [selectedDay, setSelectedDay] = useState(() => moment()); return (
- - - + + +
); } diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index c95d5bc..896fd2f 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -1,77 +1,71 @@ -import { randomColor } from 'randomcolor' -import React, { useState } from 'react'; +import "./addToDo.css"; -import { v4 as uuid } from 'uuid' +import { randomColor } from "randomcolor"; +import React, { useMemo, useState } from 'react'; -import './addToDo.css' +import { v4 as uuid } from "uuid"; const AddToDo = ({ todo, setToDo, selectedDay }) => { - const [value, setValue] = useState('') - + const [value, setValue] = useState(""); + const selectDayStr = useMemo(() => selectedDay.format("DDMMYYYY") , [selectedDay]) ; + const selectedDayTitle = useMemo(() => selectedDay.format("DD.MM.YYYY") , [selectedDay]) ; function saveToDo() { - const selectDayStr = selectedDay.format('DDMMYYYY') - if (value.trim()) { - if(todo[selectDayStr]) { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectDayStr].push({ - id: uuid(), - title: value, - status: true, - defaultPos: defaultPos(), - color: randomColor({ luminosity: 'light' }) - }); - setToDo(todoCopy); - } else { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectDayStr] = [{ - id: uuid(), - title: value, - status: true, - defaultPos: defaultPos(), - color: randomColor({ luminosity: 'light' }) - }] - setToDo(todoCopy); - } - - setValue('') + if (value.trim()) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todoCopy[selectDayStr] || [] + todoCopy[selectDayStr].push({ + id: uuid(), + title: value.trim(), + isCompleted: false, + defaultPos: defaultPos(), + color: randomColor({ luminosity: "light" }), + }) + setToDo(todoCopy); } + setValue(""); } - function keyPressAddItem(e) { - const code = e.keyCode || e.which - if (code === 13) { - saveToDo() + function onKeyPressAddItem(e) { + const code = e.charCode ; + const ENTER_CODE = 13; + if (code === ENTER_CODE) { + saveToDo(); } - } function defaultPos() { const width = document.documentElement.clientWidth; const height = document.documentElement.clientHeight; - const defaultWidth = Math.floor(Math.random() * (width < 300 ? width : width - 300)) + 1 - const defaultHeight = Math.floor(Math.random() * (height < 565 ? height : height - 565)) + 1; + const defaultWidth = + Math.floor(Math.random() * (width < 300 ? width : width - 300)) + 1; + const defaultHeight = + Math.floor(Math.random() * (height < 565 ? height : height - 565)) + 1; return { x: defaultWidth, y: defaultHeight }; } - return ( -
-
- setValue(e.target.value) } - placeholder="What to do?" - type="text" - onKeyPress={ (e) => keyPressAddItem(e) } +
+
+ setValue(e.target.value)} + placeholder="What to do?" + type="text" + onKeyPress={onKeyPressAddItem} /> - +
-

{selectedDay.format('DD.MM.YYYY')}

+

+ {selectedDayTitle} +

); }; -export default AddToDo; \ No newline at end of file +export default AddToDo; diff --git a/src/components/AddToDo/addToDo.css b/src/components/AddToDo/addToDo.css index a8a0859..f4f300f 100644 --- a/src/components/AddToDo/addToDo.css +++ b/src/components/AddToDo/addToDo.css @@ -1,29 +1,36 @@ -.addtodo_div { -display: flex; +.add-todo_block { + display: flex; justify-content: center; } -.addtodo_input { +.add-task-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.add-todo-input { background-color: inherit; - border:none; + border: none; border-bottom: 1px solid white; - color:white; - outline:none; - font-size:16px; + color: white; + outline: none; + font-size: 16px; } -.addtodo_input:active { - border:none; +.add-todo-input:active { + border: none; } -.addtodo_button { +.add-todo-button { border: 1px solid white; background-color: inherit; - color:white; + color: white; padding: 7px 12px; margin-left: 10px; } -.addtodo_selected-date { + +.add-todo-selected-date { text-align: center; font-size: 20px; -} \ No newline at end of file +} diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index 06ad87f..01fa20a 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,159 +1,198 @@ -import moment from 'moment' -import React, { useState , useEffect } from 'react'; +import "./calendar.css"; -import './calendar.css' +import moment from "moment"; +import React, { useState, useEffect } from "react"; const Calendar = ({ todo, setToDo, setSelectedDay, selectedDay }) => { - moment.updateLocale('en', { week: { dow: 1 } }); + useEffect(() => { + moment.updateLocale("en", { week: { dow: 1 } }); + }, []) + const [currentWindowCalendar, setCurrentWindowCalendar] = useState( + () => setValuesCurrWindow(moment().year(), moment().month()) + ); - const [currentWindowCalendar, setCurrentWindowCalendar] = useState(setValuesCurrWindow(moment().year(),moment().month())) const [selectMonthValue, setSelectMonthValue] = useState(moment().month()); const [selectYearValue, setSelectYearValue] = useState(moment().year()); const today = moment(); function setValuesCurrWindow(year, month, day = 1) { - const selectedDay = moment().set({ 'year': year, 'month': month, 'date': day }) - const startDay = selectedDay.clone().startOf('month').startOf('week') - let currDay = startDay.subtract(1, 'day').clone(); - const resultArrAllDays = [...Array(42)].map(() => currDay.add(1, 'day').clone()); + const selectedDay = moment().set({ year: year, month: month, date: day }); + const startDay = selectedDay.clone().startOf("month").startOf("week"); + const currDay = startDay.subtract(1, "day").clone(); + const resultArrAllDays = [...Array(42)].map(() => + currDay.add(1, "day").clone() + ); return resultArrAllDays; } - - - const defaultValues = { - years : [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025], - monthsNames : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], - weekDayNames: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - } - - + years: [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025], + monthsNames: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ], + weekDayNames: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + }; function changeMonthSelect(e) { - setSelectMonthValue(Number(e.target.value)) + setSelectMonthValue(Number(e.target.value)); } function changeYearSelect(e) { - setSelectYearValue(Number(e.target.value)) + setSelectYearValue(Number(e.target.value)); } useEffect(() => { - setCurrentWindowCalendar(setValuesCurrWindow(selectYearValue, selectMonthValue)) - }, [selectMonthValue, selectYearValue]) - - function todayClickButton() { - setSelectMonthValue(moment().month()) - setSelectYearValue(moment().year()) - setCurrentWindowCalendar(setValuesCurrWindow(moment().year(),moment().month())) + setCurrentWindowCalendar( + setValuesCurrWindow(selectYearValue, selectMonthValue) + ); + }, [selectMonthValue, selectYearValue]); + + function onTodayClick() { + setSelectMonthValue(moment().month()); + setSelectYearValue(moment().year()); + setCurrentWindowCalendar( + setValuesCurrWindow(moment().year(), moment().month()) + ); } - function nextMonthBtn() { - if(selectMonthValue === 11) { - setSelectMonthValue(0) - setSelectYearValue(selectYearValue+1) + function onNextMonthClick() { + if (selectMonthValue === 11) { + setSelectMonthValue(0); + setSelectYearValue(selectYearValue + 1); } else { - setSelectMonthValue(selectMonthValue+1) + setSelectMonthValue(selectMonthValue + 1); } } function prevMonthBtn() { - if(selectMonthValue === 0) { - setSelectMonthValue(11) - setSelectYearValue(selectYearValue-1) + if (selectMonthValue === 0) { + setSelectMonthValue(11); + setSelectYearValue(selectYearValue - 1); } else { - setSelectMonthValue(selectMonthValue - 1) + setSelectMonthValue(selectMonthValue - 1); } - } - return (
- {/* BUTTON PREV MONTH */ } - changeMonthSelect(e)} + className="calendar_select calendar_select_month" + > + {/* SELECT MONTH */} + {defaultValues.monthsNames.map((month, index) => { + return ( + + ); + })} - - - - changeYearSelect(e)} + className="calendar_select calendar_select_year" + > + {/* SELECT YEARS */} + {defaultValues.years.map((year, index) => { + return ( + + ); + })} - - {/* BUTTON NEXT MONTH */ } - + + {/* BUTTON NEXT MONTH */}
-
{/* DAYS OF WEEK (MN,FR,SUN) */ } - { - defaultValues.weekDayNames.map((dayOfWeek, index) => { - return
{ dayOfWeek }
- }) - } +
+ {/* DAYS OF WEEK (MN,FR,SUN) */} + {defaultValues.weekDayNames.map((dayOfWeek, index) => { + return ( +
+ {dayOfWeek} +
+ ); + })}
-
{/* DAYS OF MONTH, 42 DAYS */ } - { - currentWindowCalendar.map((dateItem) => { - function addClassDay(item) { - let classes; - if (item.day() === 6 || item.day() === 0) { - classes = 'weekend' - } else { - classes = '' - } - if(dateItem.isSame(selectedDay, 'day')) { - classes = 'selectedDay' - } - - return classes; - } - function addClassDate(dateItem) { - let classesDate = dateItem.isSame(today, 'day') ? 'today' : ''; - if(!(dateItem.month() === selectMonthValue)) { - classesDate += ' notThisMonthColor' - } - - return classesDate; - } +
+ {/* DAYS OF MONTH, 42 DAYS */} + {currentWindowCalendar.map((dateItem) => { - const dayItemClasses = 'dataItem ' + addClassDay(dateItem) - const dataClasses = addClassDate(dateItem) - return
{setSelectedDay(dateItem)}} className={ dayItemClasses } key={ dateItem.format('DDMMYYYY') }> -
- { dateItem.format('D') } + function addClassDay(item) { + let classes; + if (item.day() === 6 || item.day() === 0) { + classes = "weekend"; + } else { + classes = ""; + } + if (dateItem.isSame(selectedDay, "day")) { + classes = "selectedDay"; + } -
- {/*{console.log(typeof todo[dateItem.format('DDMMYYYY')])}*/} - {/*{console.log(typeof todo[dateItem.format('DDMMYYYY')] === 'object' ? todo[dateItem.format('DDMMYYYY')].length ? 'haveTaskForThisDay' : '' : '' )}*/} -
+ return classes; + } + function addClassDate(dateItem) { + let classesDate = dateItem.isSame(today, "day") ? "today" : ""; + if (!(dateItem.month() === selectMonthValue)) { + classesDate += " notThisMonthColor"; + } + return classesDate; + } + console.log() + const dayItemClasses = "dataItem " + addClassDay(dateItem); + const dataClasses = addClassDate(dateItem); + + return ( +
{ + setSelectedDay(dateItem); + }} + className={dayItemClasses} + key={dateItem.format("DDMMYYYY")} + > +
{dateItem.format("D")}
+
- }) - } + ); + })}
- -
); }; -export default Calendar; \ No newline at end of file +export default Calendar; diff --git a/src/components/Calendar/calendar.css b/src/components/Calendar/calendar.css index 08d18d9..298e23f 100644 --- a/src/components/Calendar/calendar.css +++ b/src/components/Calendar/calendar.css @@ -1,78 +1,76 @@ .calendar { - } + .select_date { display: flex; justify-content: center; padding: 15px; - } .calendar_btn { padding: 5px 10px; text-align: center; - color:white; + color: white; font-size: 20px; - border:none; + border: none; background-color: inherit; cursor: pointer; } .calendar_select { text-align: center; - color:white; + color: white; font-size: 20px; - border:none; + border: none; background-color: inherit; cursor: pointer; } + .calendar_select option { background-color: #2e2f36; } -.calendar_select_year, .calendar_select_month { +.calendar_select_year, +.calendar_select_month { width: 140px; text-align: start; padding-left: 12px; } + .today_btn { border-bottom: 1px solid gray; border-radius: 10px; } - -.calendar_select:focus, .calendar_btn:focus{ +.calendar_select:focus, +.calendar_btn:focus { outline: none; } .calendar_table { display: flex; - flex-direction:column; + flex-direction: column; width: 65%; margin: auto; - - - } .calendar_table_dates { width: 100%; display: grid; - grid-template-columns: repeat(7,1fr); - grid-template-rows: repeat(6,1fr) ; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: repeat(6, 1fr); background-color: #404040; grid-gap: 1px; border: 1px solid #404040; margin: auto; } - .dataItem { justify-items: end; display: grid; padding: 3px; - color:white; - background-color: #282B30; + color: white; + background-color: #282b30; min-width: 40px; min-height: 50px; font-size: 10px; @@ -82,29 +80,27 @@ .daysOfWeek { justify-items: end; display: grid; - grid-template-columns: repeat(7,1fr); + grid-template-columns: repeat(7, 1fr); margin: auto; width: 100%; } .dayOfWeek_Item { min-width: 40px; - } - .today { display: grid; width: 15px; height: 15px; - background-color: #EF4631; + background-color: #ef4631; border-radius: 50%; justify-content: center; align-items: center; } -.selectedDay{ -border: 1px solid cornflowerblue; +.selectedDay { + border: 1px solid cornflowerblue; } .weekend { @@ -112,7 +108,7 @@ border: 1px solid cornflowerblue; } .notThisMonthColor { - color: #53565D; + color: #53565d; } .haveTaskForThisDay { @@ -120,4 +116,4 @@ border: 1px solid cornflowerblue; border-radius: 50%; width: 15px; height: 15px; -} \ No newline at end of file +} diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index 8675126..b69f446 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -1,11 +1,15 @@ -import React from 'react'; +import './header.css' + +import React from "react"; const Header = () => { return ( -
-

To Do List

+
+

+ To Do List +

); }; -export default Header; \ No newline at end of file +export default Header; diff --git a/src/components/ListItem/ListItem.js b/src/components/ListItem/ListItem.js index 2e60f36..e143491 100644 --- a/src/components/ListItem/ListItem.js +++ b/src/components/ListItem/ListItem.js @@ -1,131 +1,148 @@ -import React, { useState } from 'react'; +import "./listitemstyle.css"; -import Draggable from 'react-draggable'; +import React, { useState, useMemo } from "react"; -import iconCross from '../../icon/cross.svg' -import { ReactComponent as Done } from '../../icon/done.svg' -import iconEdit from '../../icon/edit.svg' -import save from '../../icon/save.svg' +import Draggable from "react-draggable"; -import './listitemstyle.css' +import iconCross from "../../icon/cross.svg"; +import { ReactComponent as Done } from "../../icon/done.svg"; +import iconEdit from "../../icon/edit.svg"; +import save from "../../icon/save.svg"; - -const ListItem = ({ todo, setToDo , setSelectedDay, selectedDay}) => { - - const [edit, setEdit] = useState(null) - const [value, setValue] = useState('') - selectedDay = selectedDay.format('DDMMYYYY') +const ListItem = ({ todo, setToDo, setSelectedDay, selectedDay }) => { + const [editingId, setEditingId] = useState(null); + const [value, setValue] = useState(""); + const selectDayStr = useMemo(() => selectedDay.format("DDMMYYYY") , [selectedDay]) ; function deleteToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectedDay] = [...todo[selectedDay]].filter((obj) => obj.id !== id) + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].filter( + (obj) => obj.id !== id + ); setToDo(todoCopy); } - function statusToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectedDay] = [...todo[selectedDay]].filter((obj) => { + function isCompletedToDo(id) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].map((obj) => { if (obj.id === id) { - obj.status = !obj.status + obj.isCompleted = !obj.isCompleted; } return obj; - }) - setToDo(todoCopy) + }); + setToDo(todoCopy); } function editToDo(id, title) { - setEdit(id) - setValue(title) + setEditingId(id); + setValue(title); } function saveToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectedDay] = [...todo[selectedDay]].map((item) => { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].map((item) => { if (item.id === id) { - item.title = value + item.title = value; } return item; - }) + }); setToDo(todoCopy); - setEdit(null); + setEditingId(null); } function updatePosition(data, index) { - const todoCopy = JSON.parse(JSON.stringify(todo)) - todoCopy[selectedDay][index].defaultPos = { x: data.x, y: data.y } - setToDo(todoCopy) + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr][index].defaultPos = { x: data.x, y: data.y }; + setToDo(todoCopy); } - - - return ( -
- - { todo[selectedDay] ? - todo[selectedDay].map((item, index) => ( - - { - updatePosition(data, index) - } } - - > -
- { - edit === item.id ? +
+ {todo[selectDayStr]?.length ? ( + todo[selectDayStr].map((item, index) => ( + { + updatePosition(data, index); + }} + > +
+ {editingId === item.id ? (
- { index + 1 }. - setValue((e.target.value)) } - value={ value } - + {index + 1}. + setValue(e.target.value)} + value={value} /> -
: +
+ ) : (
{ index + 1 }. { item.title }
- } - { - - edit === item.id ? + className={ + item.isCompleted + ? "list_item-title-nochange item_done" + : "list_item-title-nochange" + } + > + {index + 1}. {item.title} +
+ )} + {editingId === item.id ? (
- -
: - +
+ ) : (
- - - -
- - - } - - -
- - )) - : -
- Tasks not found -
- } + )} +
+ + )) + ) : ( +
Tasks not found
+ )}
- ); }; -export default ListItem; \ No newline at end of file +export default ListItem; diff --git a/src/components/ListItem/listitemstyle.css b/src/components/ListItem/listitemstyle.css index 927dcda..541c656 100644 --- a/src/components/ListItem/listitemstyle.css +++ b/src/components/ListItem/listitemstyle.css @@ -5,37 +5,34 @@ min-height: 60px; justify-content: space-between; align-items: center; - color:black; + color: black; font-weight: bold; - padding:5px; + padding: 5px; border-radius: 10px; cursor: move; margin: auto; - } .listitem_btn { background-color: inherit; - border:none; + border: none; cursor: pointer; - } .list_item-input-change { margin-left: 3px; background-color: inherit; - border:none; + border: none; border-bottom: 1px solid black; font-weight: bold; - color:black; - outline:none; - font-size:16px; - font-family: 'Montserrat', sans-serif; + color: black; + outline: none; + font-size: 16px; + font-family: "Montserrat", sans-serif; } .list_item-title-nochange { - font-size:16px; + font-size: 16px; } .item_done { text-decoration: line-through; } - diff --git a/src/index.js b/src/index.js index e1e164e..ee3beae 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,6 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import App from './App'; - - -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - -); +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +const root = ReactDOM.createRoot(document.getElementById("root")); +root.render(); From d3c325a5ef88875ecca41dc60d095186740cdc96 Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Thu, 28 Jul 2022 15:51:34 +0300 Subject: [PATCH 02/12] fix small bags and code clearing --- src/components/Header/header.css | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/components/Header/header.css diff --git a/src/components/Header/header.css b/src/components/Header/header.css new file mode 100644 index 0000000..0c0dda8 --- /dev/null +++ b/src/components/Header/header.css @@ -0,0 +1,6 @@ +.header-title { + text-align: center; + font-size: 24px; + margin-top: 0; + padding-top: 20px; +} \ No newline at end of file From 256c81a4c0cda37c17f811dfe56798c46f8b43ca Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Mon, 15 Aug 2022 19:10:02 +0300 Subject: [PATCH 03/12] second fix 15.08 --- src/App.css | 2 +- src/App.js | 5 +- src/components/AddToDo/AddToDo.js | 89 ++++---- src/components/AddToDo/addToDo.css | 10 +- src/components/Calendar/Calendar.js | 202 +++--------------- .../CalendarNavigation/CalendarNavigation.js | 117 ++++++++++ .../CalendarNavigation/calendarNavigation.css | 26 +++ .../Calendar/CalendarTable/CalendarTable.js | 74 +++++++ .../Calendar/CalendarTable/calendarTable.css | 63 ++++++ src/components/Calendar/calendar.css | 114 +--------- src/components/Header/Header.js | 4 +- src/components/ListItem/ListItem.js | 148 ------------- .../ToDoItem/ToDoItem.css} | 78 +++---- src/components/ToDoList/ToDoItem/ToDoItem.js | 125 +++++++++++ src/components/ToDoList/ToDoList.js | 46 ++++ src/components/ToDoList/ToDolist.css | 11 + src/components/UI/button/MyButton.js | 13 ++ src/components/UI/button/myButton.css | 7 + src/components/UI/input/MyInput.js | 13 ++ src/components/UI/input/myInput.css | 7 + src/components/UI/select/MySelect.js | 22 ++ src/components/UI/select/mySelect.css | 10 + 22 files changed, 664 insertions(+), 522 deletions(-) create mode 100644 src/components/Calendar/CalendarNavigation/CalendarNavigation.js create mode 100644 src/components/Calendar/CalendarNavigation/calendarNavigation.css create mode 100644 src/components/Calendar/CalendarTable/CalendarTable.js create mode 100644 src/components/Calendar/CalendarTable/calendarTable.css delete mode 100644 src/components/ListItem/ListItem.js rename src/components/{ListItem/listitemstyle.css => ToDoList/ToDoItem/ToDoItem.css} (80%) create mode 100644 src/components/ToDoList/ToDoItem/ToDoItem.js create mode 100644 src/components/ToDoList/ToDoList.js create mode 100644 src/components/ToDoList/ToDolist.css create mode 100644 src/components/UI/button/MyButton.js create mode 100644 src/components/UI/button/myButton.css create mode 100644 src/components/UI/input/MyInput.js create mode 100644 src/components/UI/input/myInput.css create mode 100644 src/components/UI/select/MySelect.js create mode 100644 src/components/UI/select/mySelect.css diff --git a/src/App.css b/src/App.css index 9128af3..23be38d 100644 --- a/src/App.css +++ b/src/App.css @@ -19,7 +19,7 @@ flex-grow: 0; } -.draggable_fild { +.draggable-fild { flex-grow: 10; } diff --git a/src/App.js b/src/App.js index c2ee5a6..bb22b14 100644 --- a/src/App.js +++ b/src/App.js @@ -6,9 +6,10 @@ import React, { useEffect, useState } from 'react'; import Calendar from "./components/Calendar/Calendar"; import AddToDo from "./components/AddToDo/AddToDo"; import Header from "./components/Header/Header"; -import ListItem from "./components/ListItem/ListItem"; +import ToDoList from "./components/ToDoList/ToDoList"; function App() { + const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}); useEffect(() => { @@ -21,7 +22,7 @@ function App() {
- + { - const [value, setValue] = useState(""); - const selectDayStr = useMemo(() => selectedDay.format("DDMMYYYY") , [selectedDay]) ; - const selectedDayTitle = useMemo(() => selectedDay.format("DD.MM.YYYY") , [selectedDay]) ; + const [inputValue, setInputValue] = useState(''); + const selectDayStr = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); + const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'), [selectedDay]); - function saveToDo() { - - if (value.trim()) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todoCopy[selectDayStr] || [] - todoCopy[selectDayStr].push({ - id: uuid(), - title: value.trim(), - isCompleted: false, - defaultPos: defaultPos(), - color: randomColor({ luminosity: "light" }), - }) - setToDo(todoCopy); + function AddTask() { + if (!inputValue.trim()) { + setInputValue(''); + return; } - setValue(""); + + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todoCopy[selectDayStr] || []; + todoCopy[selectDayStr].push({ + id : uuid(), + title : inputValue.trim(), + isCompleted: false, + defaultPos : getRandomDefaultTaskPosition(), + color : randomColor({ luminosity: 'light' }) + }); + setToDo(todoCopy); + setInputValue(''); } - function onKeyPressAddItem(e) { - const code = e.charCode ; + function onKeyPressAddTask(e) { + const code = e.charCode; const ENTER_CODE = 13; if (code === ENTER_CODE) { - saveToDo(); + AddTask(); } } - function defaultPos() { - const width = document.documentElement.clientWidth; - const height = document.documentElement.clientHeight; - const defaultWidth = - Math.floor(Math.random() * (width < 300 ? width : width - 300)) + 1; - const defaultHeight = - Math.floor(Math.random() * (height < 565 ? height : height - 565)) + 1; - return { x: defaultWidth, y: defaultHeight }; - } - return (
-
- + setValue(e.target.value)} + value={ inputValue } + onChange={ (e) => setInputValue(e.target.value) } placeholder="What to do?" type="text" - onKeyPress={onKeyPressAddItem} + onKeyPress={ onKeyPressAddTask } /> - +

- {selectedDayTitle} + { selectedDayTitle }

); }; export default AddToDo; + +function getRandomDefaultTaskPosition() { + const width = document.documentElement.clientWidth; + const height = document.documentElement.clientHeight; + const WIDTH_HEADER = 300; // 300px - fix width header + const WIDTH_CALENDAR = 580; // 580px - fix width footer + const defaultWidth = + Math.floor(Math.random() * (width < WIDTH_HEADER ? width : width - WIDTH_HEADER)); + const defaultHeight = + Math.floor(Math.random() * (height < WIDTH_CALENDAR ? height : height - WIDTH_CALENDAR)); + + return { x: defaultWidth, y: defaultHeight }; +} diff --git a/src/components/AddToDo/addToDo.css b/src/components/AddToDo/addToDo.css index f4f300f..dd0bc05 100644 --- a/src/components/AddToDo/addToDo.css +++ b/src/components/AddToDo/addToDo.css @@ -1,4 +1,4 @@ -.add-todo_block { +.add-todo-block { display: flex; justify-content: center; } @@ -10,11 +10,6 @@ } .add-todo-input { - background-color: inherit; - border: none; - border-bottom: 1px solid white; - color: white; - outline: none; font-size: 16px; } @@ -24,9 +19,6 @@ .add-todo-button { border: 1px solid white; - background-color: inherit; - color: white; - padding: 7px 12px; margin-left: 10px; } diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index 01fa20a..ed4a692 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,196 +1,60 @@ -import "./calendar.css"; +import './calendar.css'; -import moment from "moment"; -import React, { useState, useEffect } from "react"; +import moment from 'moment'; +import React, { useState, useEffect } from 'react'; -const Calendar = ({ todo, setToDo, setSelectedDay, selectedDay }) => { +import CalendarNavigation from './CalendarNavigation/CalendarNavigation'; +import CalendarTable from './CalendarTable/CalendarTable'; - useEffect(() => { - moment.updateLocale("en", { week: { dow: 1 } }); - }, []) +const Calendar = ({ todo, setSelectedDay, selectedDay }) => { - const [currentWindowCalendar, setCurrentWindowCalendar] = useState( - () => setValuesCurrWindow(moment().year(), moment().month()) - ); + useEffect(() => { + moment.updateLocale('en', { week: { dow: 1 } }); + }, []); const [selectMonthValue, setSelectMonthValue] = useState(moment().month()); const [selectYearValue, setSelectYearValue] = useState(moment().year()); - const today = moment(); + const [currentWindowCalendar, setCurrentWindowCalendar] = useState( + () => createValuesCurrWindow(moment().year(), moment().month()) + ); - function setValuesCurrWindow(year, month, day = 1) { + function createValuesCurrWindow(year, month, day = 1) { const selectedDay = moment().set({ year: year, month: month, date: day }); - const startDay = selectedDay.clone().startOf("month").startOf("week"); - const currDay = startDay.subtract(1, "day").clone(); + const startDay = selectedDay.clone().startOf('month').startOf('week'); + const currDay = startDay.subtract(1, 'day').clone(); const resultArrAllDays = [...Array(42)].map(() => - currDay.add(1, "day").clone() + currDay.add(1, 'day').clone() ); return resultArrAllDays; } - const defaultValues = { - years: [2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025], - monthsNames: [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ], - weekDayNames: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], - }; - - function changeMonthSelect(e) { - setSelectMonthValue(Number(e.target.value)); - } - - function changeYearSelect(e) { - setSelectYearValue(Number(e.target.value)); - } - useEffect(() => { setCurrentWindowCalendar( - setValuesCurrWindow(selectYearValue, selectMonthValue) + createValuesCurrWindow(selectYearValue, selectMonthValue) ); }, [selectMonthValue, selectYearValue]); - function onTodayClick() { - setSelectMonthValue(moment().month()); - setSelectYearValue(moment().year()); - setCurrentWindowCalendar( - setValuesCurrWindow(moment().year(), moment().month()) - ); - } - - function onNextMonthClick() { - if (selectMonthValue === 11) { - setSelectMonthValue(0); - setSelectYearValue(selectYearValue + 1); - } else { - setSelectMonthValue(selectMonthValue + 1); - } - } - function prevMonthBtn() { - if (selectMonthValue === 0) { - setSelectMonthValue(11); - setSelectYearValue(selectYearValue - 1); - } else { - setSelectMonthValue(selectMonthValue - 1); - } - } - return (
-
- - {/* BUTTON PREV MONTH */} - - - - - {/* BUTTON NEXT MONTH */} -
- -
-
- {/* DAYS OF WEEK (MN,FR,SUN) */} - {defaultValues.weekDayNames.map((dayOfWeek, index) => { - return ( -
- {dayOfWeek} -
- ); - })} -
-
- {/* DAYS OF MONTH, 42 DAYS */} - {currentWindowCalendar.map((dateItem) => { - - - function addClassDay(item) { - let classes; - if (item.day() === 6 || item.day() === 0) { - classes = "weekend"; - } else { - classes = ""; - } - if (dateItem.isSame(selectedDay, "day")) { - classes = "selectedDay"; - } - - return classes; - } - function addClassDate(dateItem) { - let classesDate = dateItem.isSame(today, "day") ? "today" : ""; - if (!(dateItem.month() === selectMonthValue)) { - classesDate += " notThisMonthColor"; - } - - return classesDate; - } - console.log() - const dayItemClasses = "dataItem " + addClassDay(dateItem); - const dataClasses = addClassDate(dateItem); + + - return ( -
{ - setSelectedDay(dateItem); - }} - className={dayItemClasses} - key={dateItem.format("DDMMYYYY")} - > -
{dateItem.format("D")}
-
-
- ); - })} -
-
); }; diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js new file mode 100644 index 0000000..99f9916 --- /dev/null +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -0,0 +1,117 @@ +import './calendarNavigation.css' + +import React from 'react'; + +import MyButton from '../../UI/button/MyButton'; +import MySelect from '../../UI/select/MySelect'; + +import moment from 'moment'; + + +const CalendarNavigation = ({ + setSelectMonthValue, setSelectYearValue, setSelectedDay, + setCurrentWindowCalendar, createValuesCurrWindow, selectMonthValue, + selectYearValue, + }) => { + + + function onMonthSelectChange(e) { + setSelectMonthValue(Number(e.target.value)); + } + + function onYearSelectChange(e) { + setSelectYearValue(Number(e.target.value)); + } + + function onTodayClick() { + setSelectMonthValue(moment().month()); + setSelectYearValue(moment().year()); + setSelectedDay(moment()); + setCurrentWindowCalendar( + createValuesCurrWindow(moment().year(), moment().month()) + ); + } + + function onNextMonthClick() { + if (selectMonthValue === 11) { + setSelectMonthValue(0); + setSelectYearValue(selectYearValue + 1); + } else { + setSelectMonthValue(selectMonthValue + 1); + } + } + + function onPreviousMonthClick() { + if (selectMonthValue === 0) { + setSelectMonthValue(11); + setSelectYearValue(selectYearValue - 1); + } else { + setSelectMonthValue(selectMonthValue - 1); + } + } + + return ( +
+ + { '<' } + + + + + + Today + + + + + + { '>' } + +
+ ); +}; + +export default CalendarNavigation; + + + + +const defaultValuesForSelect = { + years : { + 2016: 2016, + 2017: 2017, + 2018: 2018, + 2019: 2019, + 2020: 2020, + 2021: 2021, + 2022: 2022, + 2023: 2023, + 2024: 2024, + 2025: 2025, + 2026: 2026 + }, + monthsNames : { + 0: 'January', + 1: 'February', + 2: 'March', + 3: 'April', + 4: 'May', + 5: 'June', + 6: 'July', + 7: 'August', + 8: 'September', + 9: 'October', + 10: 'November', + 11: 'December' + } +}; \ No newline at end of file diff --git a/src/components/Calendar/CalendarNavigation/calendarNavigation.css b/src/components/Calendar/CalendarNavigation/calendarNavigation.css new file mode 100644 index 0000000..b91482e --- /dev/null +++ b/src/components/Calendar/CalendarNavigation/calendarNavigation.css @@ -0,0 +1,26 @@ +.calendar-navigation { + display: flex; + justify-content: center; + padding: 15px; +} + +.calendar-button { + font-size: 20px; + border: none; +} + +.calendar-select { + font-size: 20px; + width: 140px; + padding-left: 12px; +} + +.today-button { + border-bottom: 1px solid gray; + border-radius: 10px; +} + +.calendar-select:focus, +.calendar-button:focus { + outline: none; +} \ No newline at end of file diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js new file mode 100644 index 0000000..0d16aa3 --- /dev/null +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -0,0 +1,74 @@ +import './calendarTable.css' + +import React from 'react'; +import moment from 'moment'; + +const CalendarTable = ({currentWindowCalendar, selectedDay, selectMonthValue, setSelectedDay, todo}) => { + + function addClassForAllDays(item) { + let classes; + if (item.day() === 6 || item.day() === 0) { + classes = 'weekend'; + } else { + classes = ''; + } + if (item.isSame(selectedDay, 'day')) { + classes = 'selectedDay'; + } + + return classes; + } + + function addClassForCurrentMonth(dateItem) { + let classesDate = dateItem.isSame(moment(), 'day') ? 'today' : ''; + if (!(dateItem.month() === selectMonthValue)) { + classesDate += ' notThisMonthColor'; + } + + return classesDate; + } + + + return ( + <> +
+
+ { weekDayNames.map((dayOfWeek, index) => { + return ( +
+ { dayOfWeek } +
+ ); + }) } +
+
+ { currentWindowCalendar.map((dateItem) => { + return ( +
{ + setSelectedDay(dateItem); + } } + className={'dataItem ' + addClassForAllDays(dateItem) } + key={ dateItem.format('DDMMYYYY') } + > +
{ dateItem.format('D') }
+
+
+ ); + }) } +
+
+ + ); +}; + +export default CalendarTable; + + + +const weekDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] + diff --git a/src/components/Calendar/CalendarTable/calendarTable.css b/src/components/Calendar/CalendarTable/calendarTable.css new file mode 100644 index 0000000..eeb6f2e --- /dev/null +++ b/src/components/Calendar/CalendarTable/calendarTable.css @@ -0,0 +1,63 @@ +.calendar-table-dates { + width: 100%; + display: grid; + grid-template-columns: repeat(7, 1fr); + grid-template-rows: repeat(6, 1fr); + background-color: #404040; + grid-gap: 1px; + border: 1px solid #404040; + margin: auto; +} + +.dataItem { + justify-items: end; + display: grid; + padding: 3px; + color: white; + background-color: #282b30; + min-width: 40px; + min-height: 50px; + font-size: 10px; + cursor: pointer; +} + +.table-daysOfWeek { + justify-items: end; + display: grid; + grid-template-columns: repeat(7, 1fr); + margin: auto; + width: 100%; +} + +.dayOfWeek-item { + min-width: 40px; +} + +.today { + display: grid; + width: 15px; + height: 15px; + background-color: #ef4631; + border-radius: 50%; + justify-content: center; + align-items: center; +} + +.selectedDay { + border: 1px solid cornflowerblue; +} + +.weekend { + background-color: #2e2f36; +} + +.notThisMonthColor { + color: #53565d; +} + +.haveTaskForThisDay { + background-color: blueviolet; + border-radius: 50%; + width: 15px; + height: 15px; +} \ No newline at end of file diff --git a/src/components/Calendar/calendar.css b/src/components/Calendar/calendar.css index 298e23f..45caae6 100644 --- a/src/components/Calendar/calendar.css +++ b/src/components/Calendar/calendar.css @@ -1,119 +1,9 @@ -.calendar { -} - -.select_date { - display: flex; - justify-content: center; - padding: 15px; -} - -.calendar_btn { - padding: 5px 10px; - text-align: center; - color: white; - font-size: 20px; - border: none; - background-color: inherit; - cursor: pointer; -} - -.calendar_select { - text-align: center; - color: white; - font-size: 20px; - border: none; - background-color: inherit; - cursor: pointer; -} - -.calendar_select option { - background-color: #2e2f36; -} - -.calendar_select_year, -.calendar_select_month { - width: 140px; - text-align: start; - padding-left: 12px; -} - -.today_btn { - border-bottom: 1px solid gray; - border-radius: 10px; -} - -.calendar_select:focus, -.calendar_btn:focus { - outline: none; -} - -.calendar_table { +.calendar-table { display: flex; flex-direction: column; width: 65%; + padding-bottom: 10px; margin: auto; } -.calendar_table_dates { - width: 100%; - display: grid; - grid-template-columns: repeat(7, 1fr); - grid-template-rows: repeat(6, 1fr); - background-color: #404040; - grid-gap: 1px; - border: 1px solid #404040; - margin: auto; -} - -.dataItem { - justify-items: end; - display: grid; - padding: 3px; - color: white; - background-color: #282b30; - min-width: 40px; - min-height: 50px; - font-size: 10px; - cursor: pointer; -} -.daysOfWeek { - justify-items: end; - display: grid; - grid-template-columns: repeat(7, 1fr); - margin: auto; - width: 100%; -} - -.dayOfWeek_Item { - min-width: 40px; -} - -.today { - display: grid; - width: 15px; - height: 15px; - background-color: #ef4631; - border-radius: 50%; - justify-content: center; - align-items: center; -} - -.selectedDay { - border: 1px solid cornflowerblue; -} - -.weekend { - background-color: #2e2f36; -} - -.notThisMonthColor { - color: #53565d; -} - -.haveTaskForThisDay { - background-color: blueviolet; - border-radius: 50%; - width: 15px; - height: 15px; -} diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index b69f446..22c3b9a 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -1,6 +1,6 @@ -import './header.css' +import './header.css'; -import React from "react"; +import React from 'react'; const Header = () => { return ( diff --git a/src/components/ListItem/ListItem.js b/src/components/ListItem/ListItem.js deleted file mode 100644 index e143491..0000000 --- a/src/components/ListItem/ListItem.js +++ /dev/null @@ -1,148 +0,0 @@ -import "./listitemstyle.css"; - -import React, { useState, useMemo } from "react"; - -import Draggable from "react-draggable"; - -import iconCross from "../../icon/cross.svg"; -import { ReactComponent as Done } from "../../icon/done.svg"; -import iconEdit from "../../icon/edit.svg"; -import save from "../../icon/save.svg"; - -const ListItem = ({ todo, setToDo, setSelectedDay, selectedDay }) => { - const [editingId, setEditingId] = useState(null); - const [value, setValue] = useState(""); - const selectDayStr = useMemo(() => selectedDay.format("DDMMYYYY") , [selectedDay]) ; - - function deleteToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].filter( - (obj) => obj.id !== id - ); - setToDo(todoCopy); - } - - function isCompletedToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].map((obj) => { - if (obj.id === id) { - obj.isCompleted = !obj.isCompleted; - } - return obj; - }); - setToDo(todoCopy); - } - - function editToDo(id, title) { - setEditingId(id); - setValue(title); - } - - function saveToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].map((item) => { - if (item.id === id) { - item.title = value; - } - return item; - }); - setToDo(todoCopy); - setEditingId(null); - } - - function updatePosition(data, index) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr][index].defaultPos = { x: data.x, y: data.y }; - setToDo(todoCopy); - } - - return ( -
- {todo[selectDayStr]?.length ? ( - todo[selectDayStr].map((item, index) => ( - { - updatePosition(data, index); - }} - > -
- {editingId === item.id ? ( -
- {index + 1}. - setValue(e.target.value)} - value={value} - /> -
- ) : ( -
- {index + 1}. {item.title} -
- )} - {editingId === item.id ? ( -
- -
- ) : ( -
- - - -
- )} -
-
- )) - ) : ( -
Tasks not found
- )} -
- ); -}; - -export default ListItem; diff --git a/src/components/ListItem/listitemstyle.css b/src/components/ToDoList/ToDoItem/ToDoItem.css similarity index 80% rename from src/components/ListItem/listitemstyle.css rename to src/components/ToDoList/ToDoItem/ToDoItem.css index 541c656..baa8781 100644 --- a/src/components/ListItem/listitemstyle.css +++ b/src/components/ToDoList/ToDoItem/ToDoItem.css @@ -1,38 +1,40 @@ -.list_item { - display: flex; - position: absolute; - width: 300px; - min-height: 60px; - justify-content: space-between; - align-items: center; - color: black; - font-weight: bold; - padding: 5px; - border-radius: 10px; - cursor: move; - margin: auto; -} -.listitem_btn { - background-color: inherit; - border: none; - cursor: pointer; -} - -.list_item-input-change { - margin-left: 3px; - background-color: inherit; - border: none; - border-bottom: 1px solid black; - font-weight: bold; - color: black; - outline: none; - font-size: 16px; - font-family: "Montserrat", sans-serif; -} -.list_item-title-nochange { - font-size: 16px; -} - -.item_done { - text-decoration: line-through; -} +.list-item { + display: flex; + position: absolute; + width: 300px; + min-height: 60px; + justify-content: space-between; + align-items: center; + color: black; + font-weight: bold; + padding: 5px; + border-radius: 10px; + cursor: move; + margin: auto; +} + +.list-item-input-change { + margin-left: 3px; + background-color: inherit; + border: none; + border-bottom: 1px solid black; + font-weight: bold; + color: black; + outline: none; + font-size: 16px; + font-family: "Montserrat", sans-serif; +} + +.list-item-title-nochange { + font-size: 16px; +} + +.item-done { + text-decoration: line-through; +} + +.list-item-button { + background-color: inherit; + border: none; + cursor: pointer; +} \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js new file mode 100644 index 0000000..2da789c --- /dev/null +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -0,0 +1,125 @@ +import './ToDoItem.css'; + +import React, { useState } from 'react'; + +import iconCross from '../../../icon/cross.svg'; +import { ReactComponent as Done } from '../../../icon/done.svg'; +import iconEdit from '../../../icon/edit.svg'; +import save from '../../../icon/save.svg'; + + +const ToDoItem = ({ item, index, todo, setToDo, selectDayStr }) => { + + const [value, setValue] = useState(''); + const [editingId, setEditingId] = useState(null); + + function deleteToDo(id) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].filter( + (obj) => obj.id !== id + ); + setToDo(todoCopy); + } + + function isCompletedToDo(id) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].map((obj) => { + if (obj.id === id) { + obj.isCompleted = !obj.isCompleted; + } + return obj; + }); + setToDo(todoCopy); + } + + function editToDo(id, title) { + setEditingId(id); + setValue(title); + } + + function saveToDo(id) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr] = todo[selectDayStr].map((item) => { + if (item.id === id) { + item.title = value; + } + return item; + }); + setToDo(todoCopy); + setEditingId(null); + } + + + return ( +
+ { editingId === item.id ? ( +
+ { index + 1 }. + setValue(e.target.value) } + value={ value } + /> +
+ ) : ( +
+ { index + 1 }. { item.title } +
+ ) } + { editingId === item.id ? ( +
+ +
+ ) : ( +
+ + + +
+ ) } +
+ ); +}; + +export default ToDoItem; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js new file mode 100644 index 0000000..40fabd7 --- /dev/null +++ b/src/components/ToDoList/ToDoList.js @@ -0,0 +1,46 @@ +import './ToDolist.css'; + +import React, { useMemo } from 'react'; + +import Draggable from 'react-draggable'; +import ToDoItem from './ToDoItem/ToDoItem'; + +const ToDoList = ({ todo, setToDo, selectedDay }) => { + + const selectDayStr = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); + + function updateTaskPosition(data, index) { + const todoCopy = JSON.parse(JSON.stringify(todo)); + todoCopy[selectDayStr][index].defaultPos = { x: data.x, y: data.y }; + setToDo(todoCopy); + } + + return ( +
+ { todo[selectDayStr]?.length ? ( + todo[selectDayStr].map((item, index) => ( + + { + updateTaskPosition(data, index); + } } + > +
+ +
+
+ )) + ) : ( +
Tasks not found
+ ) } +
+ ); +}; + +export default ToDoList; + + diff --git a/src/components/ToDoList/ToDolist.css b/src/components/ToDoList/ToDolist.css new file mode 100644 index 0000000..af12360 --- /dev/null +++ b/src/components/ToDoList/ToDolist.css @@ -0,0 +1,11 @@ +.draggable-element { + width: 300px; + min-height: 60px; + position: absolute; +} + +.header-taskNotFound { + text-align: center; +} + + diff --git a/src/components/UI/button/MyButton.js b/src/components/UI/button/MyButton.js new file mode 100644 index 0000000..9b3a200 --- /dev/null +++ b/src/components/UI/button/MyButton.js @@ -0,0 +1,13 @@ +import './myButton.css' + +import React from 'react'; + +const MyButton = (props) => { + return ( + + ); +}; + +export default MyButton; \ No newline at end of file diff --git a/src/components/UI/button/myButton.css b/src/components/UI/button/myButton.css new file mode 100644 index 0000000..d874692 --- /dev/null +++ b/src/components/UI/button/myButton.css @@ -0,0 +1,7 @@ +.myButton-default-style { + padding: 5px 10px; + text-align: center; + color: white; + background-color: inherit; + cursor: pointer; +} \ No newline at end of file diff --git a/src/components/UI/input/MyInput.js b/src/components/UI/input/MyInput.js new file mode 100644 index 0000000..94331ba --- /dev/null +++ b/src/components/UI/input/MyInput.js @@ -0,0 +1,13 @@ +import './myInput.css' + +import React from 'react'; + +const MyInput = (props) => { + return ( + + {props.children} + + ); +}; + +export default MyInput; \ No newline at end of file diff --git a/src/components/UI/input/myInput.css b/src/components/UI/input/myInput.css new file mode 100644 index 0000000..2664858 --- /dev/null +++ b/src/components/UI/input/myInput.css @@ -0,0 +1,7 @@ +.myInput-default-style { + background-color: inherit; + border: none; + border-bottom: 1px solid white; + color: white; + outline: none; +} \ No newline at end of file diff --git a/src/components/UI/select/MySelect.js b/src/components/UI/select/MySelect.js new file mode 100644 index 0000000..a16f963 --- /dev/null +++ b/src/components/UI/select/MySelect.js @@ -0,0 +1,22 @@ +import './mySelect.css'; + +import React from 'react'; + +const MySelect = ({ optionsObj, children, ...props }) => { + return ( + + ); +}; + +export default MySelect; \ No newline at end of file diff --git a/src/components/UI/select/mySelect.css b/src/components/UI/select/mySelect.css new file mode 100644 index 0000000..6a364dc --- /dev/null +++ b/src/components/UI/select/mySelect.css @@ -0,0 +1,10 @@ +.mySelect-default-style { + text-align: start; + color: white; + border: none; + background-color: inherit; + cursor: pointer; +} +.mySelect-default-style option { + background-color: #2e2f36; +} \ No newline at end of file From 704eea7411dbf2cc23d36eca1bd776d3a78b73b9 Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Wed, 17 Aug 2022 23:49:12 +0300 Subject: [PATCH 04/12] 16,17.08.22 --- src/App.js | 76 +++++++++-- src/components/AddToDo/AddToDo.js | 46 +++---- src/components/Calendar/Calendar.js | 29 ++--- .../CalendarNavigation/CalendarNavigation.js | 45 +++---- .../Calendar/CalendarTable/CalendarTable.js | 9 +- .../ToDoList/ToDoItem/EditTask/EditTask.js | 43 ++++++ .../ToDoList/ToDoItem/EditTask/editTask.css | 0 .../ToDoList/ToDoItem/ShowTask/ShowTask.js | 55 ++++++++ .../ToDoList/ToDoItem/ShowTask/showTask.css | 0 src/components/ToDoList/ToDoItem/ToDoItem.css | 1 + src/components/ToDoList/ToDoItem/ToDoItem.js | 123 +++--------------- src/components/ToDoList/ToDoList.js | 14 +- 12 files changed, 249 insertions(+), 192 deletions(-) create mode 100644 src/components/ToDoList/ToDoItem/EditTask/EditTask.js create mode 100644 src/components/ToDoList/ToDoItem/EditTask/editTask.css create mode 100644 src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js create mode 100644 src/components/ToDoList/ToDoItem/ShowTask/showTask.css diff --git a/src/App.js b/src/App.js index bb22b14..5542fc7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,32 +1,82 @@ -import "./App.css"; +import './App.css'; -import moment from "moment"; +import moment from 'moment'; import React, { useEffect, useState } from 'react'; -import Calendar from "./components/Calendar/Calendar"; -import AddToDo from "./components/AddToDo/AddToDo"; -import Header from "./components/Header/Header"; -import ToDoList from "./components/ToDoList/ToDoList"; +import Calendar from './components/Calendar/Calendar'; +import AddToDo from './components/AddToDo/AddToDo'; +import Header from './components/Header/Header'; +import ToDoList from './components/ToDoList/ToDoList'; function App() { const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}); + const [selectedDay, setSelectedDay] = useState(() => moment()); useEffect(() => { - localStorage.setItem("items", JSON.stringify(todo)); + localStorage.setItem('items', JSON.stringify(todo)); }, [todo]); - const [selectedDay, setSelectedDay] = useState(() => moment()); + function addSelectedDayTask(newTask, selectedDayTasksId) { + if (!todo[selectedDayTasksId]) { + todo[selectedDayTasksId] = []; + } + const copySelectDayTasks = [...todo[selectedDayTasksId]]; + copySelectDayTasks.push(newTask); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayTasks }); + } + + function deleteTaskFromSelectedDay(task, selectedDayTasksId) { + const copySelectDayToDo = todo[selectedDayTasksId].filter((element) => { + return element.id !== task.id; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function completedTask(task, selectedDayTasksId) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { + if (element.id === task.id) { + element.isCompleted = !element.isCompleted; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function updateTaskPosition(data, index, selectedDayTasksId) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element, i) => { + if (index === i) { + element.defaultPos = { x: data.x, y: data.y }; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function changeTaskTitle(task, newTitle, selectedDayTasksId) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { + if (element.id === task.id) { + element.title = newTitle; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } return (
- - + +
); diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index 6e602b1..a9b434c 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -7,37 +7,29 @@ import { v4 as uuid } from 'uuid'; import MyButton from '../UI/button/MyButton'; import MyInput from '../UI/input/MyInput'; -const AddToDo = ({ todo, setToDo, selectedDay }) => { +const AddToDo = ({addTask, selectedDay}) => { const [inputValue, setInputValue] = useState(''); - const selectDayStr = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); + const selectedDayTasksId = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'), [selectedDay]); - function AddTask() { - if (!inputValue.trim()) { - setInputValue(''); - return; - } - - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todoCopy[selectDayStr] || []; - todoCopy[selectDayStr].push({ - id : uuid(), - title : inputValue.trim(), - isCompleted: false, - defaultPos : getRandomDefaultTaskPosition(), - color : randomColor({ luminosity: 'light' }) - }); - setToDo(todoCopy); - setInputValue(''); - } function onKeyPressAddTask(e) { const code = e.charCode; const ENTER_CODE = 13; if (code === ENTER_CODE) { - AddTask(); + addTask(createNewTask(inputValue)); + } + } + + function checkAndAddTask() { + if (!inputValue.trim()) { + setInputValue(''); + return; } + const newTask = createNewTask(inputValue) + addTask(newTask, selectedDayTasksId) + setInputValue(''); } return ( @@ -51,7 +43,7 @@ const AddToDo = ({ todo, setToDo, selectedDay }) => { type="text" onKeyPress={ onKeyPressAddTask } /> - + Add a task
@@ -76,3 +68,13 @@ function getRandomDefaultTaskPosition() { return { x: defaultWidth, y: defaultHeight }; } + +function createNewTask(titleOfNewTask) { + return { + id : uuid(), + title : titleOfNewTask.trim(), + isCompleted: false, + defaultPos : getRandomDefaultTaskPosition(), + color : randomColor({ luminosity: 'light' }) + } +} \ No newline at end of file diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index ed4a692..6580687 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -38,23 +38,22 @@ const Calendar = ({ todo, setSelectedDay, selectedDay }) => { return (
- + -
); }; diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index 99f9916..b21458c 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -1,19 +1,16 @@ -import './calendarNavigation.css' +import './calendarNavigation.css'; import React from 'react'; +import moment from 'moment'; import MyButton from '../../UI/button/MyButton'; import MySelect from '../../UI/select/MySelect'; -import moment from 'moment'; - - const CalendarNavigation = ({ - setSelectMonthValue, setSelectYearValue, setSelectedDay, - setCurrentWindowCalendar, createValuesCurrWindow, selectMonthValue, - selectYearValue, - }) => { - + setSelectMonthValue, setSelectYearValue, setSelectedDay, + setCurrentWindowCalendar, createValuesCurrWindow, selectMonthValue, + selectYearValue + }) => { function onMonthSelectChange(e) { setSelectMonthValue(Number(e.target.value)); @@ -60,7 +57,7 @@ const CalendarNavigation = ({ value={ selectMonthValue } onChange={ onMonthSelectChange } className="calendar-select calendar-select-month" - optionsObj = {defaultValuesForSelect.monthsNames} + optionsObj={ defaultValuesForSelect.monthsNames } /> @@ -71,7 +68,7 @@ const CalendarNavigation = ({ value={ selectYearValue } onChange={ onYearSelectChange } className="calendar-select calendar-select-year" - optionsObj = {defaultValuesForSelect.years} + optionsObj={ defaultValuesForSelect.years } /> @@ -84,10 +81,8 @@ const CalendarNavigation = ({ export default CalendarNavigation; - - const defaultValuesForSelect = { - years : { + years : { 2016: 2016, 2017: 2017, 2018: 2018, @@ -100,17 +95,17 @@ const defaultValuesForSelect = { 2025: 2025, 2026: 2026 }, - monthsNames : { - 0: 'January', - 1: 'February', - 2: 'March', - 3: 'April', - 4: 'May', - 5: 'June', - 6: 'July', - 7: 'August', - 8: 'September', - 9: 'October', + monthsNames: { + 0 : 'January', + 1 : 'February', + 2 : 'March', + 3 : 'April', + 4 : 'May', + 5 : 'June', + 6 : 'July', + 7 : 'August', + 8 : 'September', + 9 : 'October', 10: 'November', 11: 'December' } diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index 0d16aa3..25d1974 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -1,9 +1,9 @@ -import './calendarTable.css' +import './calendarTable.css'; import React from 'react'; import moment from 'moment'; -const CalendarTable = ({currentWindowCalendar, selectedDay, selectMonthValue, setSelectedDay, todo}) => { +const CalendarTable = ({ currentWindowCalendar, selectedDay, selectMonthValue, setSelectedDay, todo }) => { function addClassForAllDays(item) { let classes; @@ -48,7 +48,7 @@ const CalendarTable = ({currentWindowCalendar, selectedDay, selectMonthValue, se onClick={ () => { setSelectedDay(dateItem); } } - className={'dataItem ' + addClassForAllDays(dateItem) } + className={ 'dataItem ' + addClassForAllDays(dateItem) } key={ dateItem.format('DDMMYYYY') } >
{ dateItem.format('D') }
@@ -69,6 +69,5 @@ const CalendarTable = ({currentWindowCalendar, selectedDay, selectMonthValue, se export default CalendarTable; - -const weekDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] +const weekDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; diff --git a/src/components/ToDoList/ToDoItem/EditTask/EditTask.js b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js new file mode 100644 index 0000000..df39f4a --- /dev/null +++ b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js @@ -0,0 +1,43 @@ +import React from 'react'; +import MyInput from '../../../UI/input/MyInput'; +import MyButton from '../../../UI/button/MyButton'; +import save from '../../../../icon/save.svg'; + +const EditTask = ({value, item, index, selectDayStr, setEditingId, onInputChange, changeTaskTitle }) => { + + + function saveToDo(item, value, selectDayStr) { + changeTaskTitle(item, value, selectDayStr) + setEditingId(null); + } + + function handlerTitleChange(e) { + onInputChange(e.target.value) + } + + return ( +
+
+ { index + 1 }. + +
+ saveToDo(item, value, selectDayStr) } + > + close + +
+ ); +}; + +export default EditTask; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/EditTask/editTask.css b/src/components/ToDoList/ToDoItem/EditTask/editTask.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js new file mode 100644 index 0000000..82b17e6 --- /dev/null +++ b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js @@ -0,0 +1,55 @@ +import React from 'react'; + +import MyButton from '../../../UI/button/MyButton'; +import iconCross from '../../../../icon/cross.svg'; +import iconEdit from '../../../../icon/edit.svg'; +import { ReactComponent as Done } from '../../../../icon/done.svg'; + +const ShowTask = ({ item, index, selectDayStr, editToDo, deleteTask, completedTask }) => { + + return ( +
+
+ { index + 1 }. { item.title } +
+
+ deleteTask(item,selectDayStr) } + > + close + + editToDo(item.id, item.title) } + > + close + + completedTask(item, selectDayStr ) } + > + + +
+
+ ); +}; + +export default ShowTask; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/ShowTask/showTask.css b/src/components/ToDoList/ToDoItem/ShowTask/showTask.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.css b/src/components/ToDoList/ToDoItem/ToDoItem.css index baa8781..2300a2e 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.css +++ b/src/components/ToDoList/ToDoItem/ToDoItem.css @@ -37,4 +37,5 @@ background-color: inherit; border: none; cursor: pointer; + padding: 1px 6px; } \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js index 2da789c..9e51b28 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.js +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -1,122 +1,39 @@ import './ToDoItem.css'; import React, { useState } from 'react'; +import EditTask from './EditTask/EditTask'; +import ShowTask from './ShowTask/ShowTask'; -import iconCross from '../../../icon/cross.svg'; -import { ReactComponent as Done } from '../../../icon/done.svg'; -import iconEdit from '../../../icon/edit.svg'; -import save from '../../../icon/save.svg'; +const ToDoItem = ({ item, index, selectDayStr, deleteTask, completedTask, changeTaskTitle }) => { - -const ToDoItem = ({ item, index, todo, setToDo, selectDayStr }) => { - - const [value, setValue] = useState(''); const [editingId, setEditingId] = useState(null); - - function deleteToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].filter( - (obj) => obj.id !== id - ); - setToDo(todoCopy); - } - - function isCompletedToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].map((obj) => { - if (obj.id === id) { - obj.isCompleted = !obj.isCompleted; - } - return obj; - }); - setToDo(todoCopy); - } + const [titleChangeInput, setTitleChangeInput] = useState(''); function editToDo(id, title) { setEditingId(id); - setValue(title); + setTitleChangeInput(title); } - function saveToDo(id) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr] = todo[selectDayStr].map((item) => { - if (item.id === id) { - item.title = value; - } - return item; - }); - setToDo(todoCopy); - setEditingId(null); + function handlerTitleChange(newTitle) { + setTitleChangeInput(newTitle); } - return ( -
- { editingId === item.id ? ( -
- { index + 1 }. - setValue(e.target.value) } - value={ value } - /> -
- ) : ( -
- { index + 1 }. { item.title } -
- ) } +
{ editingId === item.id ? ( -
- -
+ ) : ( -
- - - -
+ ) }
); diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index 40fabd7..b813107 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -5,16 +5,10 @@ import React, { useMemo } from 'react'; import Draggable from 'react-draggable'; import ToDoItem from './ToDoItem/ToDoItem'; -const ToDoList = ({ todo, setToDo, selectedDay }) => { +const ToDoList = ({ todo, selectedDay, deleteTask, completedTask, updateTaskPosition, changeTaskTitle }) => { const selectDayStr = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); - function updateTaskPosition(data, index) { - const todoCopy = JSON.parse(JSON.stringify(todo)); - todoCopy[selectDayStr][index].defaultPos = { x: data.x, y: data.y }; - setToDo(todoCopy); - } - return (
{ todo[selectDayStr]?.length ? ( @@ -25,11 +19,13 @@ const ToDoList = ({ todo, setToDo, selectedDay }) => { position={ null } defaultPosition={ item.defaultPos } onStop={ (e, data) => { - updateTaskPosition(data, index); + updateTaskPosition(data, index, selectDayStr); } } >
-
From c0afe6eb66e9d5018fb4b32dd87f66080a28ca42 Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Fri, 19 Aug 2022 00:26:56 +0300 Subject: [PATCH 05/12] 18.08 with react.memo --- package-lock.json | 41 ++++ package.json | 1 + src/App.js | 191 ++++++++++-------- src/components/AddToDo/AddToDo.js | 160 +++++++-------- src/components/AddToDo/addToDo.css | 2 + src/components/Calendar/Calendar.js | 125 ++++++------ .../CalendarNavigation/CalendarNavigation.js | 88 ++++---- .../Calendar/CalendarTable/CalendarTable.js | 62 +++--- src/components/Header/Header.js | 70 +++++-- src/components/Header/header.css | 9 +- .../ToDoList/ToDoItem/EditTask/EditTask.js | 10 +- .../ToDoList/ToDoItem/ShowTask/ShowTask.js | 8 +- src/components/ToDoList/ToDoItem/ToDoItem.js | 9 +- src/components/ToDoList/ToDoList.js | 14 +- src/components/UI/button/MyButton.js | 8 +- src/components/UI/input/MyInput.js | 8 +- src/components/UI/select/MySelect.js | 15 +- src/icon/deleteAllTasks.svg | 1 + src/icon/deleteDayTasks.svg | 1 + 19 files changed, 473 insertions(+), 350 deletions(-) create mode 100644 src/icon/deleteAllTasks.svg create mode 100644 src/icon/deleteDayTasks.svg diff --git a/package-lock.json b/package-lock.json index fcfe25e..57e56da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.5", "react-scripts": "5.0.1", + "react-tooltip": "^4.2.21", "uuid": "^8.3.2", "web-vitals": "^2.1.4" }, @@ -14051,6 +14052,30 @@ } } }, + "node_modules/react-tooltip": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", + "integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==", + "dependencies": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + }, + "engines": { + "npm": ">=6.13" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/react-tooltip/node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -26630,6 +26655,22 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-tooltip": { + "version": "4.2.21", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz", + "integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==", + "requires": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + }, + "dependencies": { + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + } + } + }, "read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 63bea57..110ee89 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.5", "react-scripts": "5.0.1", + "react-tooltip": "^4.2.21", "uuid": "^8.3.2", "web-vitals": "^2.1.4" }, diff --git a/src/App.js b/src/App.js index 5542fc7..61d65ea 100644 --- a/src/App.js +++ b/src/App.js @@ -1,85 +1,106 @@ -import './App.css'; - -import moment from 'moment'; -import React, { useEffect, useState } from 'react'; - -import Calendar from './components/Calendar/Calendar'; -import AddToDo from './components/AddToDo/AddToDo'; -import Header from './components/Header/Header'; -import ToDoList from './components/ToDoList/ToDoList'; - -function App() { - - const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}); - const [selectedDay, setSelectedDay] = useState(() => moment()); - - useEffect(() => { - localStorage.setItem('items', JSON.stringify(todo)); - }, [todo]); - - function addSelectedDayTask(newTask, selectedDayTasksId) { - if (!todo[selectedDayTasksId]) { - todo[selectedDayTasksId] = []; - } - const copySelectDayTasks = [...todo[selectedDayTasksId]]; - copySelectDayTasks.push(newTask); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayTasks }); - } - - function deleteTaskFromSelectedDay(task, selectedDayTasksId) { - const copySelectDayToDo = todo[selectedDayTasksId].filter((element) => { - return element.id !== task.id; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } - - function completedTask(task, selectedDayTasksId) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { - if (element.id === task.id) { - element.isCompleted = !element.isCompleted; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } - - function updateTaskPosition(data, index, selectedDayTasksId) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element, i) => { - if (index === i) { - element.defaultPos = { x: data.x, y: data.y }; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } - - function changeTaskTitle(task, newTitle, selectedDayTasksId) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { - if (element.id === task.id) { - element.title = newTitle; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } - - return ( -
-
- - - -
- ); -} - -export default App; +import "./App.css"; + +import moment from "moment"; +import React, { useEffect, useState, useMemo } from "react"; + +import Calendar from "./components/Calendar/Calendar"; +import AddToDo from "./components/AddToDo/AddToDo"; +import Header from "./components/Header/Header"; +import ToDoList from "./components/ToDoList/ToDoList"; + +function App() { + const [todo, setToDo] = useState( + () => JSON.parse(localStorage.getItem("items")) || {} + ); + const [selectedDay, setSelectedDay] = useState(() => moment()); + const selectedDayTasksId = useMemo( + () => selectedDay.format("DDMMYYYY"), + [selectedDay] + ); + + useEffect(() => { + localStorage.setItem("items", JSON.stringify(todo)); + }, [todo]); + + function addSelectedDayTask(newTask) { + if (!todo[selectedDayTasksId]) { + todo[selectedDayTasksId] = []; + } + const copySelectDayTasks = [...todo[selectedDayTasksId]]; + copySelectDayTasks.push(newTask); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayTasks }); + } + + function deleteTaskFromSelectedDay(task) { + const copySelectDayToDo = todo[selectedDayTasksId].filter((element) => { + return element.id !== task.id; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function completedTask(task) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { + if (element.id === task.id) { + element.isCompleted = !element.isCompleted; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function updateTaskPosition(data, index) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element, i) => { + if (index === i) { + element.defaultPos = { x: data.x, y: data.y }; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function changeTaskTitle(task, newTitle) { + const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { + if (element.id === task.id) { + element.title = newTitle; + return element; + } + return element; + }); + setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); + } + + function deleteSelectedDayAllTasks() { + setToDo({ ...todo, [selectedDayTasksId]: [] }); + } + + function deleteAllTasks() { + setToDo({}); + } + + return ( +
+
+ + + +
+ ); +} + +export default App; diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index a9b434c..72d3627 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -1,80 +1,80 @@ -import './addToDo.css'; - -import { randomColor } from 'randomcolor'; -import React, { useMemo, useState } from 'react'; - -import { v4 as uuid } from 'uuid'; -import MyButton from '../UI/button/MyButton'; -import MyInput from '../UI/input/MyInput'; - -const AddToDo = ({addTask, selectedDay}) => { - - const [inputValue, setInputValue] = useState(''); - const selectedDayTasksId = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); - const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'), [selectedDay]); - - - function onKeyPressAddTask(e) { - const code = e.charCode; - const ENTER_CODE = 13; - if (code === ENTER_CODE) { - addTask(createNewTask(inputValue)); - } - } - - function checkAndAddTask() { - if (!inputValue.trim()) { - setInputValue(''); - return; - } - const newTask = createNewTask(inputValue) - addTask(newTask, selectedDayTasksId) - setInputValue(''); - } - - return ( -
-
- setInputValue(e.target.value) } - placeholder="What to do?" - type="text" - onKeyPress={ onKeyPressAddTask } - /> - - Add a task - -
-

- { selectedDayTitle } -

-
- ); -}; - -export default AddToDo; - -function getRandomDefaultTaskPosition() { - const width = document.documentElement.clientWidth; - const height = document.documentElement.clientHeight; - const WIDTH_HEADER = 300; // 300px - fix width header - const WIDTH_CALENDAR = 580; // 580px - fix width footer - const defaultWidth = - Math.floor(Math.random() * (width < WIDTH_HEADER ? width : width - WIDTH_HEADER)); - const defaultHeight = - Math.floor(Math.random() * (height < WIDTH_CALENDAR ? height : height - WIDTH_CALENDAR)); - - return { x: defaultWidth, y: defaultHeight }; -} - -function createNewTask(titleOfNewTask) { - return { - id : uuid(), - title : titleOfNewTask.trim(), - isCompleted: false, - defaultPos : getRandomDefaultTaskPosition(), - color : randomColor({ luminosity: 'light' }) - } -} \ No newline at end of file +import "./addToDo.css"; + +import { randomColor } from "randomcolor"; +import React, { useMemo, useState } from "react"; + +import { v4 as uuid } from "uuid"; +import MyButton from "../UI/button/MyButton"; +import MyInput from "../UI/input/MyInput"; + +const AddToDo = React.memo(function AddToDo({ addTask, selectedDay }) { + const [inputValue, setInputValue] = useState(""); + const selectedDayTitle = useMemo( + () => selectedDay.format("DD.MM.YYYY"), + [selectedDay] + ); + + function onKeyPressAddTask(e) { + const code = e.charCode; + const ENTER_CODE = 13; + if (code === ENTER_CODE) { + checkAndAddTask(); + } + } + + function checkAndAddTask() { + if (!inputValue.trim()) { + setInputValue(""); + return; + } + const newTask = createNewTask(inputValue); + addTask(newTask); + setInputValue(""); + } + + return ( +
+
+ setInputValue(e.target.value)} + placeholder="What to do?" + type="text" + onKeyPress={onKeyPressAddTask} + /> + + Add a task + +
+ {selectedDayTitle} +
+ ); +}); + +export default AddToDo; + +function getRandomDefaultTaskPosition() { + const width = document.documentElement.clientWidth; + const height = document.documentElement.clientHeight; + const WIDTH_HEADER = 300; // 300px - fix width header + const WIDTH_CALENDAR = 580; // 580px - fix width footer + const defaultWidth = Math.floor( + Math.random() * (width < WIDTH_HEADER ? width : width - WIDTH_HEADER) + ); + const defaultHeight = Math.floor( + Math.random() * (height < WIDTH_CALENDAR ? height : height - WIDTH_CALENDAR) + ); + + return { x: defaultWidth, y: defaultHeight }; +} + +function createNewTask(titleOfNewTask) { + return { + id: uuid(), + title: titleOfNewTask.trim(), + isCompleted: false, + defaultPos: getRandomDefaultTaskPosition(), + color: randomColor({ luminosity: "light" }), + }; +} diff --git a/src/components/AddToDo/addToDo.css b/src/components/AddToDo/addToDo.css index dd0bc05..cda4187 100644 --- a/src/components/AddToDo/addToDo.css +++ b/src/components/AddToDo/addToDo.css @@ -23,6 +23,8 @@ } .add-todo-selected-date { + margin-top: 10px; + margin-bottom: 10px; text-align: center; font-size: 20px; } diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index 6580687..d793d0c 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,61 +1,64 @@ -import './calendar.css'; - -import moment from 'moment'; -import React, { useState, useEffect } from 'react'; - -import CalendarNavigation from './CalendarNavigation/CalendarNavigation'; -import CalendarTable from './CalendarTable/CalendarTable'; - -const Calendar = ({ todo, setSelectedDay, selectedDay }) => { - - useEffect(() => { - moment.updateLocale('en', { week: { dow: 1 } }); - }, []); - - const [selectMonthValue, setSelectMonthValue] = useState(moment().month()); - const [selectYearValue, setSelectYearValue] = useState(moment().year()); - - const [currentWindowCalendar, setCurrentWindowCalendar] = useState( - () => createValuesCurrWindow(moment().year(), moment().month()) - ); - - function createValuesCurrWindow(year, month, day = 1) { - const selectedDay = moment().set({ year: year, month: month, date: day }); - const startDay = selectedDay.clone().startOf('month').startOf('week'); - const currDay = startDay.subtract(1, 'day').clone(); - const resultArrAllDays = [...Array(42)].map(() => - currDay.add(1, 'day').clone() - ); - - return resultArrAllDays; - } - - useEffect(() => { - setCurrentWindowCalendar( - createValuesCurrWindow(selectYearValue, selectMonthValue) - ); - }, [selectMonthValue, selectYearValue]); - - return ( -
- - -
- ); -}; - -export default Calendar; +import "./calendar.css"; + +import moment from "moment"; +import React, { useState, useEffect } from "react"; + +import CalendarNavigation from "./CalendarNavigation/CalendarNavigation"; +import CalendarTable from "./CalendarTable/CalendarTable"; + +const Calendar = React.memo(function Calendar({ + todo, + setSelectedDay, + selectedDay, +}) { + useEffect(() => { + moment.updateLocale("en", { week: { dow: 1 } }); + }, []); + + const [selectMonthValue, setSelectMonthValue] = useState(moment().month()); + const [selectYearValue, setSelectYearValue] = useState(moment().year()); + + const [currentWindowCalendar, setCurrentWindowCalendar] = useState(() => + createValuesCurrWindow(moment().year(), moment().month()) + ); + + function createValuesCurrWindow(year, month, day = 1) { + const selectedDay = moment().set({ year: year, month: month, date: day }); + const startDay = selectedDay.clone().startOf("month").startOf("week"); + const currDay = startDay.subtract(1, "day").clone(); + const resultArrAllDays = [...Array(42)].map(() => + currDay.add(1, "day").clone() + ); + + return resultArrAllDays; + } + + useEffect(() => { + setCurrentWindowCalendar( + createValuesCurrWindow(selectYearValue, selectMonthValue) + ); + }, [selectMonthValue, selectYearValue]); + + return ( +
+ + +
+ ); +}); + +export default Calendar; diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index b21458c..8d4409d 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -1,17 +1,20 @@ -import './calendarNavigation.css'; - -import React from 'react'; -import moment from 'moment'; - -import MyButton from '../../UI/button/MyButton'; -import MySelect from '../../UI/select/MySelect'; - -const CalendarNavigation = ({ - setSelectMonthValue, setSelectYearValue, setSelectedDay, - setCurrentWindowCalendar, createValuesCurrWindow, selectMonthValue, - selectYearValue - }) => { - +import "./calendarNavigation.css"; + +import React from "react"; +import moment from "moment"; + +import MyButton from "../../UI/button/MyButton"; +import MySelect from "../../UI/select/MySelect"; + +const CalendarNavigation = React.memo(function CalendarNavigation({ + setSelectMonthValue, + setSelectYearValue, + setSelectedDay, + setCurrentWindowCalendar, + createValuesCurrWindow, + selectMonthValue, + selectYearValue, +}) { function onMonthSelectChange(e) { setSelectMonthValue(Number(e.target.value)); } @@ -49,40 +52,39 @@ const CalendarNavigation = ({ return (
- - { '<' } + + {"<"} - + Today - - { '>' } + + {">"}
); -}; +}); export default CalendarNavigation; - const defaultValuesForSelect = { - years : { + years: { 2016: 2016, 2017: 2017, 2018: 2018, @@ -93,20 +95,20 @@ const defaultValuesForSelect = { 2023: 2023, 2024: 2024, 2025: 2025, - 2026: 2026 + 2026: 2026, }, monthsNames: { - 0 : 'January', - 1 : 'February', - 2 : 'March', - 3 : 'April', - 4 : 'May', - 5 : 'June', - 6 : 'July', - 7 : 'August', - 8 : 'September', - 9 : 'October', - 10: 'November', - 11: 'December' - } -}; \ No newline at end of file + 0: "January", + 1: "February", + 2: "March", + 3: "April", + 4: "May", + 5: "June", + 6: "July", + 7: "August", + 8: "September", + 9: "October", + 10: "November", + 11: "December", + }, +}; diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index 25d1974..7857dee 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -1,73 +1,79 @@ -import './calendarTable.css'; +import "./calendarTable.css"; -import React from 'react'; -import moment from 'moment'; - -const CalendarTable = ({ currentWindowCalendar, selectedDay, selectMonthValue, setSelectedDay, todo }) => { +import React from "react"; +import moment from "moment"; +const CalendarTable = React.memo(function CalendarTable({ + currentWindowCalendar, + selectedDay, + selectMonthValue, + setSelectedDay, + todo, +}) { function addClassForAllDays(item) { let classes; if (item.day() === 6 || item.day() === 0) { - classes = 'weekend'; + classes = "weekend"; } else { - classes = ''; + classes = ""; } - if (item.isSame(selectedDay, 'day')) { - classes = 'selectedDay'; + if (item.isSame(selectedDay, "day")) { + classes = "selectedDay"; } return classes; } function addClassForCurrentMonth(dateItem) { - let classesDate = dateItem.isSame(moment(), 'day') ? 'today' : ''; + let classesDate = dateItem.isSame(moment(), "day") ? "today" : ""; if (!(dateItem.month() === selectMonthValue)) { - classesDate += ' notThisMonthColor'; + classesDate += " notThisMonthColor"; } return classesDate; } - return ( <>
- { weekDayNames.map((dayOfWeek, index) => { + {weekDayNames.map((dayOfWeek, index) => { return ( -
- { dayOfWeek } +
+ {dayOfWeek}
); - }) } + })}
- { currentWindowCalendar.map((dateItem) => { + {currentWindowCalendar.map((dateItem) => { return (
{ + onClick={() => { setSelectedDay(dateItem); - } } - className={ 'dataItem ' + addClassForAllDays(dateItem) } - key={ dateItem.format('DDMMYYYY') } + }} + className={"dataItem " + addClassForAllDays(dateItem)} + key={dateItem.format("DDMMYYYY")} > -
{ dateItem.format('D') }
+
+ {dateItem.format("D")} +
); - }) } + })}
); -}; +}); export default CalendarTable; - -const weekDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - +const weekDayNames = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index 22c3b9a..5467789 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -1,15 +1,55 @@ -import './header.css'; - -import React from 'react'; - -const Header = () => { - return ( -
-

- To Do List -

-
- ); -}; - -export default Header; +import "./header.css"; + +import React from "react"; +import ReactTooltip from "react-tooltip"; + +import MyButton from "../UI/button/MyButton"; +import deleteDayTasksSVG from "../../icon/deleteDayTasks.svg"; +import deleteAllTasksSVG from "../../icon/deleteAllTasks.svg"; + +const Header = React.memo(function Header({ + deleteSelectedDayAllTasks, + deleteAllTasks, +}) { + return ( +
+
+ + delete day tasks + + + Delete tasks from this day + +

To Do List

+ + delete all tasks + + + Delete ALL tasks + +
+
+ ); +}); + +export default Header; diff --git a/src/components/Header/header.css b/src/components/Header/header.css index 0c0dda8..f856924 100644 --- a/src/components/Header/header.css +++ b/src/components/Header/header.css @@ -1,6 +1,13 @@ +.header-container { +display: flex; +} +.header-buttons { + border:none; + margin: 5px; +} .header-title { text-align: center; font-size: 24px; - margin-top: 0; padding-top: 20px; + margin: 0 auto 10px; } \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/EditTask/EditTask.js b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js index df39f4a..ea24154 100644 --- a/src/components/ToDoList/ToDoItem/EditTask/EditTask.js +++ b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js @@ -3,11 +3,11 @@ import MyInput from '../../../UI/input/MyInput'; import MyButton from '../../../UI/button/MyButton'; import save from '../../../../icon/save.svg'; -const EditTask = ({value, item, index, selectDayStr, setEditingId, onInputChange, changeTaskTitle }) => { +const EditTask = React.memo(function EditTask({value, item, index, setEditingId, onInputChange, changeTaskTitle }) { - function saveToDo(item, value, selectDayStr) { - changeTaskTitle(item, value, selectDayStr) + function saveToDo(item, value) { + changeTaskTitle(item, value) setEditingId(null); } @@ -27,7 +27,7 @@ const EditTask = ({value, item, index, selectDayStr, setEditingId, onInputChange
saveToDo(item, value, selectDayStr) } + onClick={ () => saveToDo(item, value) } >
); -}; +}) export default EditTask; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js index 82b17e6..fd7f9f5 100644 --- a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js +++ b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js @@ -5,7 +5,7 @@ import iconCross from '../../../../icon/cross.svg'; import iconEdit from '../../../../icon/edit.svg'; import { ReactComponent as Done } from '../../../../icon/done.svg'; -const ShowTask = ({ item, index, selectDayStr, editToDo, deleteTask, completedTask }) => { +const ShowTask = React.memo(function ShowTask({ item, index, editToDo, deleteTask, completedTask }) { return (
@@ -21,7 +21,7 @@ const ShowTask = ({ item, index, selectDayStr, editToDo, deleteTask, completedTa
deleteTask(item,selectDayStr) } + onClick={() => deleteTask(item) } > completedTask(item, selectDayStr ) } + onClick={ () => completedTask(item) } >
); -}; +}) export default ShowTask; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js index 9e51b28..082deb5 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.js +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -4,7 +4,7 @@ import React, { useState } from 'react'; import EditTask from './EditTask/EditTask'; import ShowTask from './ShowTask/ShowTask'; -const ToDoItem = ({ item, index, selectDayStr, deleteTask, completedTask, changeTaskTitle }) => { +const ToDoItem = React.memo(function ToDoItem({ item, index, deleteTask, completedTask, changeTaskTitle }) { const [editingId, setEditingId] = useState(null); const [titleChangeInput, setTitleChangeInput] = useState(''); @@ -26,17 +26,16 @@ const ToDoItem = ({ item, index, selectDayStr, deleteTask, completedTask, change onInputChange={ handlerTitleChange } setEditingId={ setEditingId } item={ item } - index={ index } selectDayStr={ selectDayStr } /> + index={ index } /> ) : ( + index={ index } /> ) }
); -}; +}) export default ToDoItem; \ No newline at end of file diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index b813107..80a10cc 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -5,27 +5,27 @@ import React, { useMemo } from 'react'; import Draggable from 'react-draggable'; import ToDoItem from './ToDoItem/ToDoItem'; -const ToDoList = ({ todo, selectedDay, deleteTask, completedTask, updateTaskPosition, changeTaskTitle }) => { +const ToDoList = React.memo(function ToDoList({ todo, selectedDay, deleteTask, completedTask, updateTaskPosition, changeTaskTitle }) { - const selectDayStr = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); + const selectedDayTasksId = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); return (
- { todo[selectDayStr]?.length ? ( - todo[selectDayStr].map((item, index) => ( + { todo[selectedDayTasksId]?.length ? ( + todo[selectedDayTasksId].map((item, index) => ( { - updateTaskPosition(data, index, selectDayStr); + updateTaskPosition(data, index); } } >
@@ -35,7 +35,7 @@ const ToDoList = ({ todo, selectedDay, deleteTask, completedTask, updateTaskPosi ) }
); -}; +}) export default ToDoList; diff --git a/src/components/UI/button/MyButton.js b/src/components/UI/button/MyButton.js index 9b3a200..12b94d6 100644 --- a/src/components/UI/button/MyButton.js +++ b/src/components/UI/button/MyButton.js @@ -1,11 +1,11 @@ -import './myButton.css' +import "./myButton.css"; -import React from 'react'; +import React from "react"; const MyButton = (props) => { return ( - ); }; diff --git a/src/components/UI/input/MyInput.js b/src/components/UI/input/MyInput.js index 94331ba..66cb9ce 100644 --- a/src/components/UI/input/MyInput.js +++ b/src/components/UI/input/MyInput.js @@ -1,13 +1,13 @@ -import './myInput.css' +import "./myInput.css"; -import React from 'react'; +import React from "react"; const MyInput = (props) => { return ( - + {props.children} ); }; -export default MyInput; \ No newline at end of file +export default MyInput; diff --git a/src/components/UI/select/MySelect.js b/src/components/UI/select/MySelect.js index a16f963..1c66e7b 100644 --- a/src/components/UI/select/MySelect.js +++ b/src/components/UI/select/MySelect.js @@ -1,20 +1,19 @@ -import './mySelect.css'; +import "./mySelect.css"; -import React from 'react'; +import React from "react"; const MySelect = ({ optionsObj, children, ...props }) => { return ( - + { optionsObj + ? Object.keys(optionsObj).map((keyValue) => { return ( ); - }) : - children - } + }) + : children } ); }; diff --git a/src/icon/deleteAllTasks.svg b/src/icon/deleteAllTasks.svg new file mode 100644 index 0000000..647c816 --- /dev/null +++ b/src/icon/deleteAllTasks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/icon/deleteDayTasks.svg b/src/icon/deleteDayTasks.svg new file mode 100644 index 0000000..90e2394 --- /dev/null +++ b/src/icon/deleteDayTasks.svg @@ -0,0 +1 @@ + \ No newline at end of file From fd7383c064fc16020e3ec05a216d66560444dbfc Mon Sep 17 00:00:00 2001 From: andrsvsrg <62656978+andrsvsrg@users.noreply.github.com> Date: Fri, 19 Aug 2022 00:32:04 +0300 Subject: [PATCH 06/12] prettier --- .idea/.gitignore | 5 + .idea/codeStyles/Project.xml | 113 ++++++++++++++++++ .idea/codeStyles/codeStyleConfig.xml | 5 + .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/jsLibraryMappings.xml | 6 + .idea/misc.xml | 73 +++++++++++ .idea/modules.xml | 8 ++ .idea/prettier.xml | 6 + .idea/reactToDo.iml | 12 ++ .idea/vcs.xml | 6 + .../Calendar/CalendarTable/CalendarTable.js | 57 +++++---- .../ToDoList/ToDoItem/EditTask/EditTask.js | 44 +++---- .../ToDoList/ToDoItem/ShowTask/ShowTask.js | 54 ++++----- src/components/ToDoList/ToDoItem/ToDoItem.js | 53 ++++---- src/components/ToDoList/ToDoList.js | 60 ++++++---- 15 files changed, 383 insertions(+), 125 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/codeStyles/Project.xml create mode 100644 .idea/codeStyles/codeStyleConfig.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/jsLibraryMappings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/prettier.xml create mode 100644 .idea/reactToDo.iml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..b58b603 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..a4bcaef --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..290c251 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..31420c9 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000..8004ceb --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/reactToDo.iml b/.idea/reactToDo.iml new file mode 100644 index 0000000..0c8867d --- /dev/null +++ b/.idea/reactToDo.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index 7857dee..9d3eaec 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -10,29 +10,6 @@ const CalendarTable = React.memo(function CalendarTable({ setSelectedDay, todo, }) { - function addClassForAllDays(item) { - let classes; - if (item.day() === 6 || item.day() === 0) { - classes = "weekend"; - } else { - classes = ""; - } - if (item.isSame(selectedDay, "day")) { - classes = "selectedDay"; - } - - return classes; - } - - function addClassForCurrentMonth(dateItem) { - let classesDate = dateItem.isSame(moment(), "day") ? "today" : ""; - if (!(dateItem.month() === selectMonthValue)) { - classesDate += " notThisMonthColor"; - } - - return classesDate; - } - return ( <>
@@ -52,10 +29,17 @@ const CalendarTable = React.memo(function CalendarTable({ onClick={() => { setSelectedDay(dateItem); }} - className={"dataItem " + addClassForAllDays(dateItem)} + className={ + "dataItem " + addClassForAllDays(dateItem, selectedDay) + } key={dateItem.format("DDMMYYYY")} > -
+
{dateItem.format("D")}
+
- { index + 1 }. + {index + 1}.
saveToDo(item, value) } + onClick={() => saveToDo(item, value)} > - close + close
); -}) +}); -export default EditTask; \ No newline at end of file +export default EditTask; diff --git a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js index fd7f9f5..6b17eeb 100644 --- a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js +++ b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js @@ -1,55 +1,47 @@ -import React from 'react'; +import React from "react"; -import MyButton from '../../../UI/button/MyButton'; -import iconCross from '../../../../icon/cross.svg'; -import iconEdit from '../../../../icon/edit.svg'; -import { ReactComponent as Done } from '../../../../icon/done.svg'; - -const ShowTask = React.memo(function ShowTask({ item, index, editToDo, deleteTask, completedTask }) { +import MyButton from "../../../UI/button/MyButton"; +import iconCross from "../../../../icon/cross.svg"; +import iconEdit from "../../../../icon/edit.svg"; +import { ReactComponent as Done } from "../../../../icon/done.svg"; +const ShowTask = React.memo(function ShowTask({ + item, + index, + editToDo, + deleteTask, + completedTask, +}) { return ( -
+
- { index + 1 }. { item.title } + {index + 1}. {item.title}
- deleteTask(item) } - > - close + deleteTask(item)}> + close editToDo(item.id, item.title) } + onClick={() => editToDo(item.id, item.title)} > - close + close completedTask(item) } + onClick={() => completedTask(item)} >
); -}) +}); -export default ShowTask; \ No newline at end of file +export default ShowTask; diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js index 082deb5..b2f5ccb 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.js +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -1,13 +1,18 @@ -import './ToDoItem.css'; +import "./ToDoItem.css"; -import React, { useState } from 'react'; -import EditTask from './EditTask/EditTask'; -import ShowTask from './ShowTask/ShowTask'; - -const ToDoItem = React.memo(function ToDoItem({ item, index, deleteTask, completedTask, changeTaskTitle }) { +import React, { useState } from "react"; +import EditTask from "./EditTask/EditTask"; +import ShowTask from "./ShowTask/ShowTask"; +const ToDoItem = React.memo(function ToDoItem({ + item, + index, + deleteTask, + completedTask, + changeTaskTitle, +}) { const [editingId, setEditingId] = useState(null); - const [titleChangeInput, setTitleChangeInput] = useState(''); + const [titleChangeInput, setTitleChangeInput] = useState(""); function editToDo(id, title) { setEditingId(id); @@ -20,22 +25,26 @@ const ToDoItem = React.memo(function ToDoItem({ item, index, deleteTask, complet return (
- { editingId === item.id ? ( - + {editingId === item.id ? ( + ) : ( - - ) } + + )}
); -}) +}); -export default ToDoItem; \ No newline at end of file +export default ToDoItem; diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index 80a10cc..6888475 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -1,42 +1,52 @@ -import './ToDolist.css'; - -import React, { useMemo } from 'react'; - -import Draggable from 'react-draggable'; -import ToDoItem from './ToDoItem/ToDoItem'; - -const ToDoList = React.memo(function ToDoList({ todo, selectedDay, deleteTask, completedTask, updateTaskPosition, changeTaskTitle }) { - - const selectedDayTasksId = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]); +import "./ToDolist.css"; + +import React, { useMemo } from "react"; + +import Draggable from "react-draggable"; +import ToDoItem from "./ToDoItem/ToDoItem"; + +const ToDoList = React.memo(function ToDoList({ + todo, + selectedDay, + deleteTask, + completedTask, + updateTaskPosition, + changeTaskTitle, +}) { + const selectedDayTasksId = useMemo( + () => selectedDay.format("DDMMYYYY"), + [selectedDay] + ); return (
- { todo[selectedDayTasksId]?.length ? ( + {todo[selectedDayTasksId]?.length ? ( todo[selectedDayTasksId].map((item, index) => ( - { + key={item.id} + position={null} + defaultPosition={item.defaultPos} + onStop={(e, data) => { updateTaskPosition(data, index); - } } + }} >
- +
)) ) : (
Tasks not found
- ) } + )}
); -}) +}); export default ToDoList; - - From bd1e8770f913a0667bfaf2f158afbd3450b1d107 Mon Sep 17 00:00:00 2001 From: Sergey Androsov <62656978+andrsvsrg@users.noreply.github.com> Date: Fri, 19 Aug 2022 00:37:49 +0300 Subject: [PATCH 07/12] delete idea directory --- .idea/.gitignore | 5 - .idea/codeStyles/Project.xml | 113 ------------------- .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/inspectionProfiles/Project_Default.xml | 6 - .idea/jsLibraryMappings.xml | 6 - .idea/misc.xml | 73 ------------ .idea/modules.xml | 8 -- .idea/prettier.xml | 6 - .idea/reactToDo.iml | 12 -- .idea/vcs.xml | 6 - 10 files changed, 240 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/jsLibraryMappings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/prettier.xml delete mode 100644 .idea/reactToDo.iml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index a4bcaef..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml deleted file mode 100644 index d23208f..0000000 --- a/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 290c251..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 31420c9..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml deleted file mode 100644 index 8004ceb..0000000 --- a/.idea/prettier.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/reactToDo.iml b/.idea/reactToDo.iml deleted file mode 100644 index 0c8867d..0000000 --- a/.idea/reactToDo.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 3cef536fc9d19c0372ec59696c5adaf020c34fe1 Mon Sep 17 00:00:00 2001 From: andrsvsrg Date: Sat, 3 Sep 2022 00:44:09 +0300 Subject: [PATCH 08/12] update --- src/App.js | 137 +++++++----------- src/components/AddToDo/AddToDo.js | 80 +++++----- src/components/AddToDo/addToDo.css | 1 + src/components/Calendar/Calendar.js | 60 ++++---- .../CalendarNavigation/CalendarNavigation.js | 91 ++++++------ .../Calendar/CalendarTable/CalendarTable.js | 71 ++++----- src/components/Header/Header.js | 56 +++---- .../ToDoList/ToDoItem/EditTask/EditTask.js | 45 ++---- .../ToDoList/ToDoItem/ShowTask/ShowTask.js | 50 ++----- src/components/ToDoList/ToDoItem/ToDoItem.js | 83 +++++------ src/components/ToDoList/ToDoList.js | 58 +++----- src/components/UI/button/MyButton.js | 13 -- src/components/UI/input/MyInput.js | 13 -- src/components/UI/my-button/index.js | 27 ++++ .../UI/{button => my-button}/myButton.css | 4 + src/components/UI/my-input/index.js | 13 ++ .../UI/{input => my-input}/myInput.css | 0 src/components/UI/my-select/index.js | 21 +++ .../UI/{select => my-select}/mySelect.css | 0 src/components/UI/select/MySelect.js | 21 --- src/constants.js | 8 + src/index.js | 12 +- 22 files changed, 376 insertions(+), 488 deletions(-) delete mode 100644 src/components/UI/button/MyButton.js delete mode 100644 src/components/UI/input/MyInput.js create mode 100644 src/components/UI/my-button/index.js rename src/components/UI/{button => my-button}/myButton.css (70%) create mode 100644 src/components/UI/my-input/index.js rename src/components/UI/{input => my-input}/myInput.css (100%) create mode 100644 src/components/UI/my-select/index.js rename src/components/UI/{select => my-select}/mySelect.css (100%) delete mode 100644 src/components/UI/select/MySelect.js create mode 100644 src/constants.js diff --git a/src/App.js b/src/App.js index 61d65ea..e8220d5 100644 --- a/src/App.js +++ b/src/App.js @@ -1,106 +1,77 @@ -import "./App.css"; +import './App.css' -import moment from "moment"; -import React, { useEffect, useState, useMemo } from "react"; +import moment from 'moment' +import React, { useEffect, useState, useMemo, useCallback } from 'react' -import Calendar from "./components/Calendar/Calendar"; -import AddToDo from "./components/AddToDo/AddToDo"; -import Header from "./components/Header/Header"; -import ToDoList from "./components/ToDoList/ToDoList"; +import Calendar from './components/Calendar/Calendar' +import AddToDo from './components/AddToDo/AddToDo' +import Header from './components/Header/Header' +import ToDoList from './components/ToDoList/ToDoList' function App() { - const [todo, setToDo] = useState( - () => JSON.parse(localStorage.getItem("items")) || {} - ); - const [selectedDay, setSelectedDay] = useState(() => moment()); - const selectedDayTasksId = useMemo( - () => selectedDay.format("DDMMYYYY"), - [selectedDay] - ); + const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}) + const [selectedDay, setSelectedDay] = useState(() => moment()) + const selectedDayTasksKey = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]) useEffect(() => { - localStorage.setItem("items", JSON.stringify(todo)); - }, [todo]); + localStorage.setItem('items', JSON.stringify(todo)) + }, [todo]) - function addSelectedDayTask(newTask) { - if (!todo[selectedDayTasksId]) { - todo[selectedDayTasksId] = []; - } - const copySelectDayTasks = [...todo[selectedDayTasksId]]; - copySelectDayTasks.push(newTask); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayTasks }); - } + const addTask = useCallback( + (newTask) => { + const selectedDayTasks = todo[selectedDayTasksKey] + const newDayTask = selectedDayTasks ? [...selectedDayTasks, newTask] : [newTask] + setToDo({ ...todo, [selectedDayTasksKey]: newDayTask }) + }, + [todo, selectedDayTasksKey], + ) - function deleteTaskFromSelectedDay(task) { - const copySelectDayToDo = todo[selectedDayTasksId].filter((element) => { - return element.id !== task.id; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } + const deleteTaskFromSelectedDay = useCallback( + (task) => { + const newSelectDayToDo = todo[selectedDayTasksKey].filter(({ id }) => { + return id !== task.id + }) + setToDo({ ...todo, [selectedDayTasksKey]: newSelectDayToDo }) + }, + [todo, selectedDayTasksKey], + ) - function completedTask(task) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { - if (element.id === task.id) { - element.isCompleted = !element.isCompleted; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } + const updateTask = useCallback( + (taskId, changes) => { + const newSelectedDayToDo = todo[selectedDayTasksKey].map((task) => { + if (task.id !== taskId) { + return task + } + return { ...task, ...changes } + }) - function updateTaskPosition(data, index) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element, i) => { - if (index === i) { - element.defaultPos = { x: data.x, y: data.y }; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } + setToDo({ ...todo, [selectedDayTasksKey]: newSelectedDayToDo }) + }, + [todo, selectedDayTasksKey], + ) - function changeTaskTitle(task, newTitle) { - const copySelectDayToDo = todo[selectedDayTasksId].map((element) => { - if (element.id === task.id) { - element.title = newTitle; - return element; - } - return element; - }); - setToDo({ ...todo, [selectedDayTasksId]: copySelectDayToDo }); - } + const deleteSelectedDayAllTasks = useCallback(() => { + setToDo({ ...todo, [selectedDayTasksKey]: [] }) + }, [todo, selectedDayTasksKey]) - function deleteSelectedDayAllTasks() { - setToDo({ ...todo, [selectedDayTasksId]: [] }); - } - - function deleteAllTasks() { - setToDo({}); - } + const deleteAllTasks = useCallback(() => { + setToDo({}) + }, []) return (
-
- +
+ - +
- ); + ) } -export default App; +export default React.memo(App) diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index 72d3627..9f326c3 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -1,72 +1,64 @@ -import "./addToDo.css"; +import './addToDo.css' -import { randomColor } from "randomcolor"; -import React, { useMemo, useState } from "react"; +import { randomColor } from 'randomcolor' +import React, { useMemo, useState } from 'react' -import { v4 as uuid } from "uuid"; -import MyButton from "../UI/button/MyButton"; -import MyInput from "../UI/input/MyInput"; +import { v4 as uuid } from 'uuid' +import { Button } from '../UI/my-button/index' +import { Input } from '../UI/my-input/index' -const AddToDo = React.memo(function AddToDo({ addTask, selectedDay }) { - const [inputValue, setInputValue] = useState(""); - const selectedDayTitle = useMemo( - () => selectedDay.format("DD.MM.YYYY"), - [selectedDay] - ); +import { fixSize, keyCode } from '../../constants' - function onKeyPressAddTask(e) { - const code = e.charCode; - const ENTER_CODE = 13; - if (code === ENTER_CODE) { - checkAndAddTask(); +const AddToDo = ({ addTask, selectedDay }) => { + const [inputValue, setInputValue] = useState('') + const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'),[selectedDay]) + + function onAddTask(e) { + const code = e.charCode + if (code === keyCode.ENTER) { + addNewTask() } } - function checkAndAddTask() { - if (!inputValue.trim()) { - setInputValue(""); - return; - } - const newTask = createNewTask(inputValue); - addTask(newTask); - setInputValue(""); + function addNewTask() { + const newTask = createNewTask(inputValue) + addTask(newTask) + setInputValue('') } + const isDisabledButton = !inputValue.trim() + return (
- setInputValue(e.target.value)} placeholder="What to do?" type="text" - onKeyPress={onKeyPressAddTask} + onKeyPress={onAddTask} /> - +
{selectedDayTitle}
- ); -}); + ) +} -export default AddToDo; +export default React.memo(AddToDo) function getRandomDefaultTaskPosition() { - const width = document.documentElement.clientWidth; - const height = document.documentElement.clientHeight; - const WIDTH_HEADER = 300; // 300px - fix width header - const WIDTH_CALENDAR = 580; // 580px - fix width footer - const defaultWidth = Math.floor( - Math.random() * (width < WIDTH_HEADER ? width : width - WIDTH_HEADER) - ); + const width = document.documentElement.clientWidth + const height = document.documentElement.clientHeight + const defaultWidth = Math.floor(Math.random() * (width < fixSize.WIDTH_HEADER ? width : width - fixSize.WIDTH_HEADER)) const defaultHeight = Math.floor( - Math.random() * (height < WIDTH_CALENDAR ? height : height - WIDTH_CALENDAR) - ); + Math.random() * (height < fixSize.WIDTH_CALENDAR ? height : height - fixSize.WIDTH_CALENDAR), + ) - return { x: defaultWidth, y: defaultHeight }; + return { x: defaultWidth, y: defaultHeight } } function createNewTask(titleOfNewTask) { @@ -75,6 +67,6 @@ function createNewTask(titleOfNewTask) { title: titleOfNewTask.trim(), isCompleted: false, defaultPos: getRandomDefaultTaskPosition(), - color: randomColor({ luminosity: "light" }), - }; + color: randomColor({ luminosity: 'light' }), + } } diff --git a/src/components/AddToDo/addToDo.css b/src/components/AddToDo/addToDo.css index cda4187..370591b 100644 --- a/src/components/AddToDo/addToDo.css +++ b/src/components/AddToDo/addToDo.css @@ -28,3 +28,4 @@ text-align: center; font-size: 20px; } + diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index d793d0c..953e6da 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,43 +1,26 @@ -import "./calendar.css"; +import './calendar.css' -import moment from "moment"; -import React, { useState, useEffect } from "react"; +import moment from 'moment' +import React, { useState, useEffect } from 'react' -import CalendarNavigation from "./CalendarNavigation/CalendarNavigation"; -import CalendarTable from "./CalendarTable/CalendarTable"; +import CalendarNavigation from './CalendarNavigation/CalendarNavigation' +import CalendarTable from './CalendarTable/CalendarTable' -const Calendar = React.memo(function Calendar({ - todo, - setSelectedDay, - selectedDay, -}) { +function Calendar({ todo, setSelectedDay, selectedDay }) { useEffect(() => { - moment.updateLocale("en", { week: { dow: 1 } }); - }, []); + moment.updateLocale('en', { week: { dow: 1 } }) + }, []) - const [selectMonthValue, setSelectMonthValue] = useState(moment().month()); - const [selectYearValue, setSelectYearValue] = useState(moment().year()); + const [selectMonthValue, setSelectMonthValue] = useState(() => moment().month()) + const [selectYearValue, setSelectYearValue] = useState(() => moment().year()) const [currentWindowCalendar, setCurrentWindowCalendar] = useState(() => - createValuesCurrWindow(moment().year(), moment().month()) - ); - - function createValuesCurrWindow(year, month, day = 1) { - const selectedDay = moment().set({ year: year, month: month, date: day }); - const startDay = selectedDay.clone().startOf("month").startOf("week"); - const currDay = startDay.subtract(1, "day").clone(); - const resultArrAllDays = [...Array(42)].map(() => - currDay.add(1, "day").clone() - ); - - return resultArrAllDays; - } + createValuesCurrWindow(moment().year(), moment().month()), + ) useEffect(() => { - setCurrentWindowCalendar( - createValuesCurrWindow(selectYearValue, selectMonthValue) - ); - }, [selectMonthValue, selectYearValue]); + setCurrentWindowCalendar(createValuesCurrWindow(selectYearValue, selectMonthValue)) + }, [selectMonthValue, selectYearValue]) return (
@@ -58,7 +41,16 @@ const Calendar = React.memo(function Calendar({ todo={todo} />
- ); -}); + ) +} + +export default React.memo(Calendar) + +function createValuesCurrWindow(year, month, day = 1) { + const selectedDay = moment().set({ year: year, month: month, date: day }) + const startDay = selectedDay.clone().startOf('month').startOf('week') + const currDay = startDay.subtract(1, 'day').clone() + const resultArrAllDays = [...Array(42)].map(() => currDay.add(1, 'day').clone()) -export default Calendar; + return resultArrAllDays +} diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index 8d4409d..08d089b 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -1,12 +1,12 @@ -import "./calendarNavigation.css"; +import './calendarNavigation.css' -import React from "react"; -import moment from "moment"; +import React from 'react' +import moment from 'moment' -import MyButton from "../../UI/button/MyButton"; -import MySelect from "../../UI/select/MySelect"; +import { Button } from '../../UI/my-button/index' +import { Select } from '../../UI/my-select/index' -const CalendarNavigation = React.memo(function CalendarNavigation({ +function CalendarNavigation({ setSelectMonthValue, setSelectYearValue, setSelectedDay, @@ -16,72 +16,70 @@ const CalendarNavigation = React.memo(function CalendarNavigation({ selectYearValue, }) { function onMonthSelectChange(e) { - setSelectMonthValue(Number(e.target.value)); + setSelectMonthValue(Number(e.target.value)) } function onYearSelectChange(e) { - setSelectYearValue(Number(e.target.value)); + setSelectYearValue(Number(e.target.value)) } function onTodayClick() { - setSelectMonthValue(moment().month()); - setSelectYearValue(moment().year()); - setSelectedDay(moment()); - setCurrentWindowCalendar( - createValuesCurrWindow(moment().year(), moment().month()) - ); + setSelectMonthValue(moment().month()) + setSelectYearValue(moment().year()) + setSelectedDay(moment()) + setCurrentWindowCalendar(createValuesCurrWindow(moment().year(), moment().month())) } function onNextMonthClick() { if (selectMonthValue === 11) { - setSelectMonthValue(0); - setSelectYearValue(selectYearValue + 1); + setSelectMonthValue(0) + setSelectYearValue(selectYearValue + 1) } else { - setSelectMonthValue(selectMonthValue + 1); + setSelectMonthValue(selectMonthValue + 1) } } function onPreviousMonthClick() { if (selectMonthValue === 0) { - setSelectMonthValue(11); - setSelectYearValue(selectYearValue - 1); + setSelectMonthValue(11) + setSelectYearValue(selectYearValue - 1) } else { - setSelectMonthValue(selectMonthValue - 1); + setSelectMonthValue(selectMonthValue - 1) } } return (
- - {"<"} - + - - + - - - {">"} - +
- ); -}); + ) +} -export default CalendarNavigation; +export default React.memo(CalendarNavigation) const defaultValuesForSelect = { years: { @@ -98,17 +96,18 @@ const defaultValuesForSelect = { 2026: 2026, }, monthsNames: { - 0: "January", - 1: "February", - 2: "March", - 3: "April", - 4: "May", - 5: "June", - 6: "July", - 7: "August", - 8: "September", - 9: "October", - 10: "November", - 11: "December", + /// moment()._locale._months + 0: 'January', + 1: 'February', + 2: 'March', + 3: 'April', + 4: 'May', + 5: 'June', + 6: 'July', + 7: 'August', + 8: 'September', + 9: 'October', + 10: 'November', + 11: 'December', }, -}; +} diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index 9d3eaec..c9e8ae3 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -1,15 +1,9 @@ -import "./calendarTable.css"; +import './calendarTable.css' -import React from "react"; -import moment from "moment"; +import React from 'react' +import moment from 'moment' -const CalendarTable = React.memo(function CalendarTable({ - currentWindowCalendar, - selectedDay, - selectMonthValue, - setSelectedDay, - todo, -}) { +function CalendarTable({ currentWindowCalendar, selectedDay, selectMonthValue, setSelectedDay, todo }) { return ( <>
@@ -19,7 +13,7 @@ const CalendarTable = React.memo(function CalendarTable({
{dayOfWeek}
- ); + ) })}
@@ -27,60 +21,45 @@ const CalendarTable = React.memo(function CalendarTable({ return (
{ - setSelectedDay(dateItem); + setSelectedDay(dateItem) }} - className={ - "dataItem " + addClassForAllDays(dateItem, selectedDay) - } - key={dateItem.format("DDMMYYYY")} + className={'dataItem ' + addClassForAllDays(dateItem, selectedDay)} + key={dateItem.format('DDMMYYYY')} > -
- {dateItem.format("D")} -
-
+
{dateItem.format('D')}
+
- ); + ) })}
- ); -}); + ) +} -export default CalendarTable; +export default React.memo(CalendarTable) -const weekDayNames = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; +const weekDayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] function addClassForAllDays(item, selectedDay) { - let classes; + let classes if (item.day() === 6 || item.day() === 0) { - classes = "weekend"; + classes = 'weekend' } else { - classes = ""; + classes = '' } - if (item.isSame(selectedDay, "day")) { - classes = "selectedDay"; + if (item.isSame(selectedDay, 'day')) { + classes = 'selectedDay' } - return classes; + return classes } function addClassForCurrentMonth(dateItem, selectMonthValue) { - let classesDate = dateItem.isSame(moment(), "day") ? "today" : ""; + let classesDate = dateItem.isSame(moment(), 'day') ? 'today' : '' if (!(dateItem.month() === selectMonthValue)) { - classesDate += " notThisMonthColor"; + classesDate += ' notThisMonthColor' } - return classesDate; -} \ No newline at end of file + return classesDate +} diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index 5467789..c14ceef 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -1,55 +1,35 @@ -import "./header.css"; +import './header.css' -import React from "react"; -import ReactTooltip from "react-tooltip"; +import React from 'react' +import ReactTooltip from 'react-tooltip' -import MyButton from "../UI/button/MyButton"; -import deleteDayTasksSVG from "../../icon/deleteDayTasks.svg"; -import deleteAllTasksSVG from "../../icon/deleteAllTasks.svg"; +import { Button } from '../UI/my-button/index' +import deleteDayTasksSVG from '../../icon/deleteDayTasks.svg' +import deleteAllTasksSVG from '../../icon/deleteAllTasks.svg' -const Header = React.memo(function Header({ - deleteSelectedDayAllTasks, - deleteAllTasks, -}) { +function Header({ deleteSelectedDayAllTasks, deleteAllTasks }) { return (
- - delete day tasks - - - Delete tasks from this day - + delete day tasks + +

To Do List

- - delete all tasks - + Delete ALL tasks
- ); -}); + ) +} -export default Header; +export default React.memo(Header) diff --git a/src/components/ToDoList/ToDoItem/EditTask/EditTask.js b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js index db4fc0f..b83669e 100644 --- a/src/components/ToDoList/ToDoItem/EditTask/EditTask.js +++ b/src/components/ToDoList/ToDoItem/EditTask/EditTask.js @@ -1,43 +1,30 @@ -import React from "react"; -import MyInput from "../../../UI/input/MyInput"; -import MyButton from "../../../UI/button/MyButton"; -import save from "../../../../icon/save.svg"; +import React from 'react' +import { Input } from '../../../UI/my-input/index' +import { Button } from '../../../UI/my-button/index' +import save from '../../../../icon/save.svg' -const EditTask = React.memo(function EditTask({ - value, - item, - index, - setEditingId, - onInputChange, - changeTaskTitle, -}) { - function saveToDo(item, value) { - changeTaskTitle(item, value); - setEditingId(null); +function EditTask({ value, item, index, setEditingId, onInputChange, updateTask }) { + function saveToDo(id, value) { + const newTitle = { title: value } + updateTask(id, newTitle) + setEditingId(null) } function handlerTitleChange(e) { - onInputChange(e.target.value); + onInputChange(e.target.value) } return (
{index + 1}. - +
- saveToDo(item, value)} - > +
- ); -}); + ) +} -export default EditTask; +export default React.memo(EditTask) diff --git a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js index 6b17eeb..9c0185f 100644 --- a/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js +++ b/src/components/ToDoList/ToDoItem/ShowTask/ShowTask.js @@ -1,47 +1,29 @@ -import React from "react"; +import React from 'react' -import MyButton from "../../../UI/button/MyButton"; -import iconCross from "../../../../icon/cross.svg"; -import iconEdit from "../../../../icon/edit.svg"; -import { ReactComponent as Done } from "../../../../icon/done.svg"; +import { Button } from '../../../UI/my-button/index' +import iconCross from '../../../../icon/cross.svg' +import iconEdit from '../../../../icon/edit.svg' +import { ReactComponent as Done } from '../../../../icon/done.svg' -const ShowTask = React.memo(function ShowTask({ - item, - index, - editToDo, - deleteTask, - completedTask, -}) { +function ShowTask({ item, index, editToDo, deleteTask, updateTask }) { return (
-
+
{index + 1}. {item.title}
- deleteTask(item)}> + + +
- ); -}); + ) +} -export default ShowTask; +export default React.memo(ShowTask) diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js index b2f5ccb..049c788 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.js +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -1,50 +1,51 @@ -import "./ToDoItem.css"; +import './ToDoItem.css' -import React, { useState } from "react"; -import EditTask from "./EditTask/EditTask"; -import ShowTask from "./ShowTask/ShowTask"; +import Draggable from 'react-draggable' +import React, { useCallback, useState } from 'react' -const ToDoItem = React.memo(function ToDoItem({ - item, - index, - deleteTask, - completedTask, - changeTaskTitle, -}) { - const [editingId, setEditingId] = useState(null); - const [titleChangeInput, setTitleChangeInput] = useState(""); +import EditTask from './EditTask/EditTask' +import ShowTask from './ShowTask/ShowTask' - function editToDo(id, title) { - setEditingId(id); - setTitleChangeInput(title); - } +function ToDoItem({ item, index, deleteTask, updateTask }) { + const [editingId, setEditingId] = useState(null) + const [titleChangeInput, setTitleChangeInput] = useState('') - function handlerTitleChange(newTitle) { - setTitleChangeInput(newTitle); - } + const editToDo = useCallback((id, title) => { + setEditingId(id) + setTitleChangeInput(title) + }, []) + + const handlerTitleChange = useCallback((newTitle) => { + setTitleChangeInput(newTitle) + }, []) return (
- {editingId === item.id ? ( - - ) : ( - - )} + { + updateTask(item.id, { defaultPos: { x: data.x, y: data.y } }) + }} + > +
+ {editingId === item.id ? ( + + ) : ( + + )} +
+
- ); -}); + ) +} -export default ToDoItem; +export default React.memo(ToDoItem) diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index 6888475..84ec74f 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -1,52 +1,30 @@ -import "./ToDolist.css"; +import './ToDolist.css' -import React, { useMemo } from "react"; +import React from 'react' -import Draggable from "react-draggable"; -import ToDoItem from "./ToDoItem/ToDoItem"; - -const ToDoList = React.memo(function ToDoList({ - todo, - selectedDay, - deleteTask, - completedTask, - updateTaskPosition, - changeTaskTitle, -}) { - const selectedDayTasksId = useMemo( - () => selectedDay.format("DDMMYYYY"), - [selectedDay] - ); +import ToDoItem from './ToDoItem/ToDoItem' +function ToDoList({ todo, selectedDay, deleteTask, completedTask, changeTaskTitle, selectedDayTasksKey, updateTask }) { return (
- {todo[selectedDayTasksId]?.length ? ( - todo[selectedDayTasksId].map((item, index) => ( - ( + { - updateTaskPosition(data, index); - }} - > -
- -
-
+ changeTaskTitle={changeTaskTitle} + completedTask={completedTask} + deleteTask={deleteTask} + selectedDay={selectedDay} + item={item} + index={index} + /> )) ) : (
Tasks not found
)}
- ); -}); + ) +} -export default ToDoList; +export default React.memo(ToDoList) diff --git a/src/components/UI/button/MyButton.js b/src/components/UI/button/MyButton.js deleted file mode 100644 index 12b94d6..0000000 --- a/src/components/UI/button/MyButton.js +++ /dev/null @@ -1,13 +0,0 @@ -import "./myButton.css"; - -import React from "react"; - -const MyButton = (props) => { - return ( - - ); -}; - -export default MyButton; \ No newline at end of file diff --git a/src/components/UI/input/MyInput.js b/src/components/UI/input/MyInput.js deleted file mode 100644 index 66cb9ce..0000000 --- a/src/components/UI/input/MyInput.js +++ /dev/null @@ -1,13 +0,0 @@ -import "./myInput.css"; - -import React from "react"; - -const MyInput = (props) => { - return ( - - {props.children} - - ); -}; - -export default MyInput; diff --git a/src/components/UI/my-button/index.js b/src/components/UI/my-button/index.js new file mode 100644 index 0000000..9c7dc58 --- /dev/null +++ b/src/components/UI/my-button/index.js @@ -0,0 +1,27 @@ +import './myButton.css' + +import React from 'react' +import ReactTooltip from 'react-tooltip' + +export const Button = (props) => { + const classNames = 'myButton-default-style ' + props.className + + if (props.tooltip) { + const tooltipType = props['tooltip-type'] ? props['tooltip-type'] : 'error' + + return ( + + ) + } + + return ( + + ) +} diff --git a/src/components/UI/button/myButton.css b/src/components/UI/my-button/myButton.css similarity index 70% rename from src/components/UI/button/myButton.css rename to src/components/UI/my-button/myButton.css index d874692..07c3743 100644 --- a/src/components/UI/button/myButton.css +++ b/src/components/UI/my-button/myButton.css @@ -4,4 +4,8 @@ color: white; background-color: inherit; cursor: pointer; +} +button:disabled { + opacity: 50%; + cursor: default; } \ No newline at end of file diff --git a/src/components/UI/my-input/index.js b/src/components/UI/my-input/index.js new file mode 100644 index 0000000..79a1aae --- /dev/null +++ b/src/components/UI/my-input/index.js @@ -0,0 +1,13 @@ +import './myInput.css' + +import React from 'react' + +export const Input = (props) => { + const classNames = 'myInput-default-style ' + props.className + + return ( + + {props.children} + + ) +} diff --git a/src/components/UI/input/myInput.css b/src/components/UI/my-input/myInput.css similarity index 100% rename from src/components/UI/input/myInput.css rename to src/components/UI/my-input/myInput.css diff --git a/src/components/UI/my-select/index.js b/src/components/UI/my-select/index.js new file mode 100644 index 0000000..9dad99c --- /dev/null +++ b/src/components/UI/my-select/index.js @@ -0,0 +1,21 @@ +import './mySelect.css' + +import React from 'react' + +export const Select = ({ optionsObj, children, ...props }) => { + const classNames = 'mySelect-default-style ' + props.className + + return ( + + ) +} diff --git a/src/components/UI/select/mySelect.css b/src/components/UI/my-select/mySelect.css similarity index 100% rename from src/components/UI/select/mySelect.css rename to src/components/UI/my-select/mySelect.css diff --git a/src/components/UI/select/MySelect.js b/src/components/UI/select/MySelect.js deleted file mode 100644 index 1c66e7b..0000000 --- a/src/components/UI/select/MySelect.js +++ /dev/null @@ -1,21 +0,0 @@ -import "./mySelect.css"; - -import React from "react"; - -const MySelect = ({ optionsObj, children, ...props }) => { - return ( - - ); -}; - -export default MySelect; \ No newline at end of file diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..b1c097c --- /dev/null +++ b/src/constants.js @@ -0,0 +1,8 @@ +export const keyCode = { + ENTER: 13, + TAB: 9, +} +export const fixSize = { + WIDTH_HEADER: 300, + WIDTH_CALENDAR: 580, +} diff --git a/src/index.js b/src/index.js index ee3beae..e1d532f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App"; - -const root = ReactDOM.createRoot(document.getElementById("root")); -root.render(); +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' + +const root = ReactDOM.createRoot(document.getElementById('root')) +root.render() From fd5e7643e1755047812e8411bca98ee5be3b35f2 Mon Sep 17 00:00:00 2001 From: andrsvsrg Date: Sun, 4 Sep 2022 17:05:22 +0300 Subject: [PATCH 09/12] calendar update --- src/App.js | 28 +++--- src/components/AddToDo/AddToDo.js | 11 ++- src/components/Calendar/Calendar.js | 29 +++++-- .../CalendarNavigation/CalendarNavigation.js | 45 ++-------- .../Calendar/CalendarTable/CalendarTable.js | 49 ++++++----- src/components/Header/Header.js | 12 +-- src/components/ToDoList/ToDoList.js | 6 +- src/{ => components/utils}/constants.js | 4 + src/components/utils/data.js | 85 +++++++++++++++++++ 9 files changed, 174 insertions(+), 95 deletions(-) rename src/{ => components/utils}/constants.js (70%) create mode 100644 src/components/utils/data.js diff --git a/src/App.js b/src/App.js index e8220d5..9b5a7db 100644 --- a/src/App.js +++ b/src/App.js @@ -10,8 +10,8 @@ import ToDoList from './components/ToDoList/ToDoList' function App() { const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}) - const [selectedDay, setSelectedDay] = useState(() => moment()) - const selectedDayTasksKey = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]) + const [selectedDay, setSelectedDay] = useState(() => moment().format('DDMMYYYY')) + // const selectedDayTasksKey = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]) useEffect(() => { localStorage.setItem('items', JSON.stringify(todo)) @@ -19,40 +19,40 @@ function App() { const addTask = useCallback( (newTask) => { - const selectedDayTasks = todo[selectedDayTasksKey] + const selectedDayTasks = todo[selectedDay] const newDayTask = selectedDayTasks ? [...selectedDayTasks, newTask] : [newTask] - setToDo({ ...todo, [selectedDayTasksKey]: newDayTask }) + setToDo({ ...todo, [selectedDay]: newDayTask }) }, - [todo, selectedDayTasksKey], + [todo, selectedDay], ) const deleteTaskFromSelectedDay = useCallback( (task) => { - const newSelectDayToDo = todo[selectedDayTasksKey].filter(({ id }) => { + const newSelectDayToDo = todo[selectedDay].filter(({ id }) => { return id !== task.id }) - setToDo({ ...todo, [selectedDayTasksKey]: newSelectDayToDo }) + setToDo({ ...todo, [selectedDay]: newSelectDayToDo }) }, - [todo, selectedDayTasksKey], + [todo, selectedDay], ) const updateTask = useCallback( (taskId, changes) => { - const newSelectedDayToDo = todo[selectedDayTasksKey].map((task) => { + const newSelectedDayToDo = todo[selectedDay].map((task) => { if (task.id !== taskId) { return task } return { ...task, ...changes } }) - setToDo({ ...todo, [selectedDayTasksKey]: newSelectedDayToDo }) + setToDo({ ...todo, [selectedDay]: newSelectedDayToDo }) }, - [todo, selectedDayTasksKey], + [todo, selectedDay], ) const deleteSelectedDayAllTasks = useCallback(() => { - setToDo({ ...todo, [selectedDayTasksKey]: [] }) - }, [todo, selectedDayTasksKey]) + setToDo({ ...todo, [selectedDay]: [] }) + }, [todo, selectedDay]) const deleteAllTasks = useCallback(() => { setToDo({}) @@ -67,7 +67,7 @@ function App() { selectedDay={selectedDay} todo={todo} deleteTask={deleteTaskFromSelectedDay} - selectedDayTasksKey={selectedDayTasksKey} + // selectedDayTasksKey={selectedDayTasksKey} />
diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index 9f326c3..66107ab 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -7,11 +7,11 @@ import { v4 as uuid } from 'uuid' import { Button } from '../UI/my-button/index' import { Input } from '../UI/my-input/index' -import { fixSize, keyCode } from '../../constants' +import { fixSize, keyCode } from '../utils/constants' const AddToDo = ({ addTask, selectedDay }) => { const [inputValue, setInputValue] = useState('') - const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'),[selectedDay]) + // const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'), [selectedDay]) function onAddTask(e) { const code = e.charCode @@ -26,6 +26,11 @@ const AddToDo = ({ addTask, selectedDay }) => { setInputValue('') } + const selectedDateTitle = useMemo( + () => `${selectedDay.slice(0, 2)}.${selectedDay.slice(2, 4)}.${selectedDay.slice(4)}`, + [selectedDay], + ) + const isDisabledButton = !inputValue.trim() return ( @@ -43,7 +48,7 @@ const AddToDo = ({ addTask, selectedDay }) => { Add a task
- {selectedDayTitle} + {selectedDateTitle}
) } diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index 953e6da..b75124b 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -3,6 +3,7 @@ import './calendar.css' import moment from 'moment' import React, { useState, useEffect } from 'react' +import { createDayMetods, getCurrentMonth, getCurrentYear } from '../utils/data' import CalendarNavigation from './CalendarNavigation/CalendarNavigation' import CalendarTable from './CalendarTable/CalendarTable' @@ -11,15 +12,15 @@ function Calendar({ todo, setSelectedDay, selectedDay }) { moment.updateLocale('en', { week: { dow: 1 } }) }, []) - const [selectMonthValue, setSelectMonthValue] = useState(() => moment().month()) - const [selectYearValue, setSelectYearValue] = useState(() => moment().year()) + const [selectMonthValue, setSelectMonthValue] = useState(() => getCurrentMonth()) + const [selectYearValue, setSelectYearValue] = useState(() => getCurrentYear()) const [currentWindowCalendar, setCurrentWindowCalendar] = useState(() => - createValuesCurrWindow(moment().year(), moment().month()), + createAllDaysForCurrWindow(getCurrentYear(), getCurrentMonth()), ) useEffect(() => { - setCurrentWindowCalendar(createValuesCurrWindow(selectYearValue, selectMonthValue)) + setCurrentWindowCalendar(createAllDaysForCurrWindow(selectYearValue, selectMonthValue)) }, [selectMonthValue, selectYearValue]) return ( @@ -29,7 +30,7 @@ function Calendar({ todo, setSelectedDay, selectedDay }) { setSelectMonthValue={setSelectMonthValue} setSelectedDay={setSelectedDay} setCurrentWindowCalendar={setCurrentWindowCalendar} - createValuesCurrWindow={createValuesCurrWindow} + createValuesCurrWindow={createAllDaysForCurrWindow} selectMonthValue={selectMonthValue} selectYearValue={selectYearValue} /> @@ -46,11 +47,25 @@ function Calendar({ todo, setSelectedDay, selectedDay }) { export default React.memo(Calendar) -function createValuesCurrWindow(year, month, day = 1) { +function createOneDay(newDay, selectMonthValue) { + return { + id: createDayMetods.getId(newDay), + date: { + day: createDayMetods.getDayOfMonth(newDay), + month: createDayMetods.getMonthOfYear(newDay), + year: createDayMetods.getYear(newDay), + }, + isWeekend: createDayMetods.isWeekend(newDay), + isCurrentMonth: createDayMetods.isCurrentMonth(newDay, selectMonthValue), + isToday: createDayMetods.isToday(newDay), + } +} + +function createAllDaysForCurrWindow(year, month, day = 1) { const selectedDay = moment().set({ year: year, month: month, date: day }) const startDay = selectedDay.clone().startOf('month').startOf('week') const currDay = startDay.subtract(1, 'day').clone() - const resultArrAllDays = [...Array(42)].map(() => currDay.add(1, 'day').clone()) + const resultArrAllDays = [...Array(42)].map(() => createOneDay(currDay.add(1, 'day').clone(), month)) return resultArrAllDays } diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index 08d089b..4b2d954 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -1,10 +1,10 @@ import './calendarNavigation.css' import React from 'react' -import moment from 'moment' import { Button } from '../../UI/my-button/index' import { Select } from '../../UI/my-select/index' +import { getCurrentMonth, getCurrentYear, getTodayDayId, monthNamesArr, yearsValues } from '../../utils/data' function CalendarNavigation({ setSelectMonthValue, @@ -24,10 +24,10 @@ function CalendarNavigation({ } function onTodayClick() { - setSelectMonthValue(moment().month()) - setSelectYearValue(moment().year()) - setSelectedDay(moment()) - setCurrentWindowCalendar(createValuesCurrWindow(moment().year(), moment().month())) + setSelectMonthValue(() => getCurrentMonth()) + setSelectYearValue(() => getCurrentYear()) + setSelectedDay(() => getTodayDayId()) + setCurrentWindowCalendar(createValuesCurrWindow(getCurrentYear(), getCurrentMonth())) } function onNextMonthClick() { @@ -58,7 +58,7 @@ function CalendarNavigation({ value={selectMonthValue} onChange={onMonthSelectChange} className="calendar-select calendar-select-month" - optionsObj={defaultValuesForSelect.monthsNames} + optionsObj={monthNamesArr} />

To Do List

- - - Delete ALL tasks -
) diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index 84ec74f..283a091 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -4,11 +4,11 @@ import React from 'react' import ToDoItem from './ToDoItem/ToDoItem' -function ToDoList({ todo, selectedDay, deleteTask, completedTask, changeTaskTitle, selectedDayTasksKey, updateTask }) { +function ToDoList({ todo, selectedDay, deleteTask, completedTask, changeTaskTitle, updateTask }) { return (
- {todo[selectedDayTasksKey]?.length ? ( - todo[selectedDayTasksKey].map((item, index) => ( + {todo[selectedDay]?.length ? ( + todo[selectedDay].map((item, index) => ( { + console.log('op') +} diff --git a/src/components/utils/data.js b/src/components/utils/data.js new file mode 100644 index 0000000..120a9de --- /dev/null +++ b/src/components/utils/data.js @@ -0,0 +1,85 @@ +import moment from 'moment' + +export const monthNamesArr = moment()._locale._months + +export function isSelectedDay(dayObj, selectedDay) { + return dayObj.id === selectedDay +} + +export function getTodayDayId() { + return moment().format('DDMMYYYY') +} + +export function getCurrentYear() { + return moment().year() +} + +export function getCurrentMonth() { + return moment().month() +} + +export const createDayMetods = { + getMonthOfYear: function getMonthOfYear(momentDay) { + return momentDay.month() + 1 + }, + getYear: function getYear(momentDay) { + return momentDay.year() + }, + isCurrentMonth: function isCurrentMonth(momentDay, selectMonth) { + return momentDay.month() === selectMonth + }, + getId: function getId(momentDay) { + return momentDay.format('DDMMYYYY') + }, + isToday: function isToday(momentDay) { + return momentDay.isSame(moment(), 'day') + }, + isWeekend: function isWeekend(momentDay) { + return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 + }, + getDayOfMonth: function getDayOfMonth(momentDay) { + return momentDay.date() + }, +} + +export const yearsValues = { + 2016: 2016, + 2017: 2017, + 2018: 2018, + 2019: 2019, + 2020: 2020, + 2021: 2021, + 2022: 2022, + 2023: 2023, + 2024: 2024, + 2025: 2025, + 2026: 2026, +} + +// export const isWeekend = (momentDay) => { +// return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 +// } +// +// export function getDayOfMonth(momentDay) { +// return momentDay.date() +// } +// +// export function getMonthOfYear(momentDay) { +// return momentDay.month() + 1 +// } +// +// export function getYear(momentDay) { +// return momentDay.year() +// } +// +// export function isCurrentMonth(momentDay, selectMonth) { +// return momentDay.month() === selectMonth +// } +// +// export function getId(momentDay) { +// return momentDay.format('DDMMYYYY') +// } +// +// export function isToday(momentDay) { +// return momentDay.isSame(moment(), 'day') +// } From ed1536a40b0aaa5a4487825e52ea3cccab130d0f Mon Sep 17 00:00:00 2001 From: andrsvsrg Date: Sun, 4 Sep 2022 17:45:57 +0300 Subject: [PATCH 10/12] calendar small fix --- src/App.js | 15 +-- src/components/Calendar/Calendar.js | 22 ++--- .../CalendarNavigation/CalendarNavigation.js | 8 +- src/components/utils/data.js | 96 +++++++++---------- 4 files changed, 67 insertions(+), 74 deletions(-) diff --git a/src/App.js b/src/App.js index 9b5a7db..fbf67d0 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,16 @@ import './App.css' -import moment from 'moment' -import React, { useEffect, useState, useMemo, useCallback } from 'react' +import React, { useEffect, useState, useCallback } from 'react' import Calendar from './components/Calendar/Calendar' import AddToDo from './components/AddToDo/AddToDo' import Header from './components/Header/Header' import ToDoList from './components/ToDoList/ToDoList' +import { getTodayDayId } from './components/utils/data' function App() { const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}) - const [selectedDay, setSelectedDay] = useState(() => moment().format('DDMMYYYY')) - // const selectedDayTasksKey = useMemo(() => selectedDay.format('DDMMYYYY'), [selectedDay]) + const [selectedDay, setSelectedDay] = useState(() => getTodayDayId()) useEffect(() => { localStorage.setItem('items', JSON.stringify(todo)) @@ -62,13 +61,7 @@ function App() {
- +
) diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index b75124b..b47d321 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -3,7 +3,7 @@ import './calendar.css' import moment from 'moment' import React, { useState, useEffect } from 'react' -import { createDayMetods, getCurrentMonth, getCurrentYear } from '../utils/data' +import * as DateUtils from '../utils/data' import CalendarNavigation from './CalendarNavigation/CalendarNavigation' import CalendarTable from './CalendarTable/CalendarTable' @@ -12,11 +12,11 @@ function Calendar({ todo, setSelectedDay, selectedDay }) { moment.updateLocale('en', { week: { dow: 1 } }) }, []) - const [selectMonthValue, setSelectMonthValue] = useState(() => getCurrentMonth()) - const [selectYearValue, setSelectYearValue] = useState(() => getCurrentYear()) + const [selectMonthValue, setSelectMonthValue] = useState(() => DateUtils.getCurrentMonth()) + const [selectYearValue, setSelectYearValue] = useState(() => DateUtils.getCurrentYear()) const [currentWindowCalendar, setCurrentWindowCalendar] = useState(() => - createAllDaysForCurrWindow(getCurrentYear(), getCurrentMonth()), + createAllDaysForCurrWindow(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth()), ) useEffect(() => { @@ -49,15 +49,15 @@ export default React.memo(Calendar) function createOneDay(newDay, selectMonthValue) { return { - id: createDayMetods.getId(newDay), + id: DateUtils.getId(newDay), date: { - day: createDayMetods.getDayOfMonth(newDay), - month: createDayMetods.getMonthOfYear(newDay), - year: createDayMetods.getYear(newDay), + day: DateUtils.getDayOfMonth(newDay), + month: DateUtils.getMonthOfYear(newDay), + year: DateUtils.getYear(newDay), }, - isWeekend: createDayMetods.isWeekend(newDay), - isCurrentMonth: createDayMetods.isCurrentMonth(newDay, selectMonthValue), - isToday: createDayMetods.isToday(newDay), + isWeekend: DateUtils.isWeekend(newDay), + isCurrentMonth: DateUtils.isCurrentMonth(newDay, selectMonthValue), + isToday: DateUtils.isToday(newDay), } } diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index 4b2d954..f634a2f 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -33,18 +33,18 @@ function CalendarNavigation({ function onNextMonthClick() { if (selectMonthValue === 11) { setSelectMonthValue(0) - setSelectYearValue(selectYearValue + 1) + setSelectYearValue((prev) => prev + 1) } else { - setSelectMonthValue(selectMonthValue + 1) + setSelectMonthValue((prev) => prev + 1) } } function onPreviousMonthClick() { if (selectMonthValue === 0) { setSelectMonthValue(11) - setSelectYearValue(selectYearValue - 1) + setSelectYearValue((prev) => prev - 1) } else { - setSelectMonthValue(selectMonthValue - 1) + setSelectMonthValue((prev) => prev - 1) } } diff --git a/src/components/utils/data.js b/src/components/utils/data.js index 120a9de..27ecbfe 100644 --- a/src/components/utils/data.js +++ b/src/components/utils/data.js @@ -18,28 +18,32 @@ export function getCurrentMonth() { return moment().month() } -export const createDayMetods = { - getMonthOfYear: function getMonthOfYear(momentDay) { - return momentDay.month() + 1 - }, - getYear: function getYear(momentDay) { - return momentDay.year() - }, - isCurrentMonth: function isCurrentMonth(momentDay, selectMonth) { - return momentDay.month() === selectMonth - }, - getId: function getId(momentDay) { - return momentDay.format('DDMMYYYY') - }, - isToday: function isToday(momentDay) { - return momentDay.isSame(moment(), 'day') - }, - isWeekend: function isWeekend(momentDay) { - return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 - }, - getDayOfMonth: function getDayOfMonth(momentDay) { - return momentDay.date() - }, +export const isWeekend = (momentDay) => { + return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 +} + +export function getDayOfMonth(momentDay) { + return momentDay.date() +} + +export function getMonthOfYear(momentDay) { + return momentDay.month() + 1 +} + +export function getYear(momentDay) { + return momentDay.year() +} + +export function isCurrentMonth(momentDay, selectMonth) { + return momentDay.month() === selectMonth +} + +export function getId(momentDay) { + return momentDay.format('DDMMYYYY') +} + +export function isToday(momentDay) { + return momentDay.isSame(moment(), 'day') } export const yearsValues = { @@ -56,30 +60,26 @@ export const yearsValues = { 2026: 2026, } -// export const isWeekend = (momentDay) => { -// return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 -// } -// -// export function getDayOfMonth(momentDay) { -// return momentDay.date() -// } -// -// export function getMonthOfYear(momentDay) { -// return momentDay.month() + 1 -// } -// -// export function getYear(momentDay) { -// return momentDay.year() -// } -// -// export function isCurrentMonth(momentDay, selectMonth) { -// return momentDay.month() === selectMonth -// } -// -// export function getId(momentDay) { -// return momentDay.format('DDMMYYYY') -// } -// -// export function isToday(momentDay) { -// return momentDay.isSame(moment(), 'day') +// export const createDayMetods = { +// getMonthOfYear: function getMonthOfYear(momentDay) { +// return momentDay.month() + 1 +// }, +// getYear: function getYear(momentDay) { +// return momentDay.year() +// }, +// isCurrentMonth: function isCurrentMonth(momentDay, selectMonth) { +// return momentDay.month() === selectMonth +// }, +// getId: function getId(momentDay) { +// return momentDay.format('DDMMYYYY') +// }, +// isToday: function isToday(momentDay) { +// return momentDay.isSame(moment(), 'day') +// }, +// isWeekend: function isWeekend(momentDay) { +// return momentDay.isoWeekday() === 6 || momentDay.isoWeekday() === 7 +// }, +// getDayOfMonth: function getDayOfMonth(momentDay) { +// return momentDay.date() +// }, // } From b67b5561f4bda9330351a506a4626359a78b8e85 Mon Sep 17 00:00:00 2001 From: andrsvsrg Date: Sat, 24 Sep 2022 15:58:02 +0300 Subject: [PATCH 11/12] add redux --- .prettierrc | 7 + package-lock.json | 490 ++++++++++++++++++ package.json | 10 +- src/App.js | 58 +-- src/components/AddToDo/AddToDo.js | 13 +- src/components/Calendar/Calendar.js | 64 +-- .../CalendarNavigation/CalendarNavigation.js | 50 +- .../Calendar/CalendarTable/CalendarTable.js | 14 +- src/components/Header/Header.js | 10 +- .../ToDoList/ToDoItem/EditTask/EditTask.js | 8 +- .../ToDoList/ToDoItem/ShowTask/ShowTask.js | 13 +- src/components/ToDoList/ToDoItem/ToDoItem.js | 15 +- src/components/ToDoList/ToDoList.js | 21 +- src/components/utils/data.js | 26 + src/constants/actions-types/calendar.js | 3 + src/constants/actions-types/index.js | 2 + src/constants/actions-types/todos.js | 8 + .../utils => constants}/constants.js | 4 - src/index.js | 19 +- src/redux/actions/calendar-actions.js | 22 + src/redux/actions/todos-actions.js | 48 ++ src/redux/reducers/calendar/index.js | 24 + src/redux/reducers/index.js | 8 + src/redux/reducers/todos/index.js | 62 +++ src/redux/selectors/todo-selectors.js | 3 + 25 files changed, 841 insertions(+), 161 deletions(-) create mode 100644 .prettierrc create mode 100644 src/constants/actions-types/calendar.js create mode 100644 src/constants/actions-types/index.js create mode 100644 src/constants/actions-types/todos.js rename src/{components/utils => constants}/constants.js (70%) create mode 100644 src/redux/actions/calendar-actions.js create mode 100644 src/redux/actions/todos-actions.js create mode 100644 src/redux/reducers/calendar/index.js create mode 100644 src/redux/reducers/index.js create mode 100644 src/redux/reducers/todos/index.js create mode 100644 src/redux/selectors/todo-selectors.js diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..729f927 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 120 +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 57e56da..02732ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,13 +12,18 @@ "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "classnames": "^2.3.1", + "gh-pages": "^4.0.0", "moment": "^2.29.4", "randomcolor": "^0.6.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-draggable": "^4.4.5", + "react-redux": "^8.0.2", "react-scripts": "5.0.1", "react-tooltip": "^4.2.21", + "redux": "^4.2.0", + "redux-thunk": "^2.4.1", + "thunk": "^0.0.1", "uuid": "^8.3.2", "web-vitals": "^2.1.4" }, @@ -3680,6 +3685,15 @@ "@types/node": "*" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -3990,6 +4004,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -4661,6 +4680,14 @@ "node": ">=8" } }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -6561,6 +6588,11 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.185.tgz", "integrity": "sha512-9kV/isoOGpKkBt04yYNaSWIBn3187Q5VZRtoReq8oz5NY/A4XmU6cAoqgQlDp7kKJCZMRjWZ8nsQyxfpFHvfyw==" }, + "node_modules/email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -7789,6 +7821,30 @@ "node": ">=10" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -8241,6 +8297,95 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", + "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", + "dependencies": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/gh-pages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/gh-pages/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -8438,6 +8583,19 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -12234,6 +12392,25 @@ "node": ">=0.10.0" } }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -12242,6 +12419,11 @@ "node": ">= 6" } }, + "node_modules/pjs": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/pjs/-/pjs-5.1.2.tgz", + "integrity": "sha512-aoPrjtnYOknat/wiO5hyCkub7LymxSY1BN8gIsW49PfbdPyQiaU+UOo9DfSEhhl48cWLd28IwpERutBveLdQLA==" + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -13972,6 +14154,49 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-redux": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz", + "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==", + "dependencies": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "peerDependencies": { + "@types/react": "^16.8 || ^17.0 || ^18.0", + "@types/react-dom": "^16.8 || ^17.0 || ^18.0", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0", + "react-native": ">=0.59", + "redux": "^4" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -14142,6 +14367,22 @@ "node": ">=8" } }, + "node_modules/redux": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", + "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/redux-thunk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "peerDependencies": { + "redux": "^4" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -15150,6 +15391,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -15504,6 +15756,17 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" }, + "node_modules/thunk": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/thunk/-/thunk-0.0.1.tgz", + "integrity": "sha512-pmOMtF63oJP7v+Hka9yRmcoPVeLGZtq2S0NwAh+rE8guWEOcg27dddYsJYZSJiKg4DTs/i71eaUDEvyCuTDNrg==", + "dependencies": { + "pjs": "*" + }, + "engines": { + "node": "*" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -15573,6 +15836,17 @@ "node": ">=8" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -15819,6 +16093,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19289,6 +19571,15 @@ "@types/node": "*" } }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -19561,6 +19852,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "@types/use-sync-external-store": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", + "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -20047,6 +20343,11 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" + }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -21432,6 +21733,11 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.185.tgz", "integrity": "sha512-9kV/isoOGpKkBt04yYNaSWIBn3187Q5VZRtoReq8oz5NY/A4XmU6cAoqgQlDp7kKJCZMRjWZ8nsQyxfpFHvfyw==" }, + "email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, "emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -22338,6 +22644,21 @@ } } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==" + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -22642,6 +22963,78 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-4.0.0.tgz", + "integrity": "sha512-p8S0T3aGJc68MtwOcZusul5qPSNZCalap3NWbhRUZYu1YOdp+EjZ+4kPmRM8h3NNRdqw00yuevRjlkuSzCn7iQ==", + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -22781,6 +23174,21 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -25524,11 +25932,29 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" }, + "pjs": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/pjs/-/pjs-5.1.2.tgz", + "integrity": "sha512-aoPrjtnYOknat/wiO5hyCkub7LymxSY1BN8gIsW49PfbdPyQiaU+UOo9DfSEhhl48cWLd28IwpERutBveLdQLA==" + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -26595,6 +27021,26 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-redux": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz", + "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==", + "requires": { + "@babel/runtime": "^7.12.1", + "@types/hoist-non-react-statics": "^3.3.1", + "@types/use-sync-external-store": "^0.0.3", + "hoist-non-react-statics": "^3.3.2", + "react-is": "^18.0.0", + "use-sync-external-store": "^1.0.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -26724,6 +27170,20 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", + "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "redux-thunk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "requires": {} + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -27471,6 +27931,14 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -27727,6 +28195,14 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" }, + "thunk": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/thunk/-/thunk-0.0.1.tgz", + "integrity": "sha512-pmOMtF63oJP7v+Hka9yRmcoPVeLGZtq2S0NwAh+rE8guWEOcg27dddYsJYZSJiKg4DTs/i71eaUDEvyCuTDNrg==", + "requires": { + "pjs": "*" + } + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -27780,6 +28256,14 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -27952,6 +28436,12 @@ "punycode": "^2.1.0" } }, + "use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 110ee89..93cf1a7 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,24 @@ "name": "codemu", "version": "0.1.0", "private": true, + "homepage": "https://andrsvsrg.github.io/reactToDo/", "dependencies": { "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.3.0", "@testing-library/user-event": "^13.5.0", "classnames": "^2.3.1", + "gh-pages": "^4.0.0", "moment": "^2.29.4", "randomcolor": "^0.6.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-draggable": "^4.4.5", + "react-redux": "^8.0.2", "react-scripts": "5.0.1", "react-tooltip": "^4.2.21", + "redux": "^4.2.0", + "redux-thunk": "^2.4.1", + "thunk": "^0.0.1", "uuid": "^8.3.2", "web-vitals": "^2.1.4" }, @@ -21,7 +27,9 @@ "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "predeploy": "react-scripts build", + "deploy": "gh-pages -d build" }, "eslintConfig": { "extends": [ diff --git a/src/App.js b/src/App.js index fbf67d0..fd9e1e7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,68 +1,28 @@ import './App.css' -import React, { useEffect, useState, useCallback } from 'react' +import React, { useEffect } from 'react' import Calendar from './components/Calendar/Calendar' import AddToDo from './components/AddToDo/AddToDo' import Header from './components/Header/Header' import ToDoList from './components/ToDoList/ToDoList' -import { getTodayDayId } from './components/utils/data' + +import { useSelector } from 'react-redux' +import { getTodo } from './redux/selectors/todo-selectors' function App() { - const [todo, setToDo] = useState(() => JSON.parse(localStorage.getItem('items')) || {}) - const [selectedDay, setSelectedDay] = useState(() => getTodayDayId()) + const todo = useSelector(getTodo) useEffect(() => { localStorage.setItem('items', JSON.stringify(todo)) }, [todo]) - const addTask = useCallback( - (newTask) => { - const selectedDayTasks = todo[selectedDay] - const newDayTask = selectedDayTasks ? [...selectedDayTasks, newTask] : [newTask] - setToDo({ ...todo, [selectedDay]: newDayTask }) - }, - [todo, selectedDay], - ) - - const deleteTaskFromSelectedDay = useCallback( - (task) => { - const newSelectDayToDo = todo[selectedDay].filter(({ id }) => { - return id !== task.id - }) - setToDo({ ...todo, [selectedDay]: newSelectDayToDo }) - }, - [todo, selectedDay], - ) - - const updateTask = useCallback( - (taskId, changes) => { - const newSelectedDayToDo = todo[selectedDay].map((task) => { - if (task.id !== taskId) { - return task - } - return { ...task, ...changes } - }) - - setToDo({ ...todo, [selectedDay]: newSelectedDayToDo }) - }, - [todo, selectedDay], - ) - - const deleteSelectedDayAllTasks = useCallback(() => { - setToDo({ ...todo, [selectedDay]: [] }) - }, [todo, selectedDay]) - - const deleteAllTasks = useCallback(() => { - setToDo({}) - }, []) - return (
-
- - - +
+ + +
) } diff --git a/src/components/AddToDo/AddToDo.js b/src/components/AddToDo/AddToDo.js index 66107ab..341cff3 100644 --- a/src/components/AddToDo/AddToDo.js +++ b/src/components/AddToDo/AddToDo.js @@ -7,11 +7,16 @@ import { v4 as uuid } from 'uuid' import { Button } from '../UI/my-button/index' import { Input } from '../UI/my-input/index' -import { fixSize, keyCode } from '../utils/constants' +import { fixSize, keyCode } from '../../constants/constants' +import { useDispatch, useSelector } from 'react-redux' +import { addTask } from '../../redux/actions/todos-actions' +import { getSelectedDay } from '../../redux/selectors/todo-selectors' -const AddToDo = ({ addTask, selectedDay }) => { +const AddToDo = () => { const [inputValue, setInputValue] = useState('') - // const selectedDayTitle = useMemo(() => selectedDay.format('DD.MM.YYYY'), [selectedDay]) + + const dispatch = useDispatch() + const selectedDay = useSelector(getSelectedDay) function onAddTask(e) { const code = e.charCode @@ -22,7 +27,7 @@ const AddToDo = ({ addTask, selectedDay }) => { function addNewTask() { const newTask = createNewTask(inputValue) - addTask(newTask) + dispatch(addTask(newTask)) setInputValue('') } diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index b47d321..c61eb9f 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,71 +1,35 @@ import './calendar.css' import moment from 'moment' -import React, { useState, useEffect } from 'react' +import React, { useEffect } from 'react' -import * as DateUtils from '../utils/data' import CalendarNavigation from './CalendarNavigation/CalendarNavigation' import CalendarTable from './CalendarTable/CalendarTable' +import * as DateUtils from '../utils/data' +import { useDispatch, useSelector } from 'react-redux' +import { changeWindowCalendar } from '../../redux/actions/calendar-actions' -function Calendar({ todo, setSelectedDay, selectedDay }) { +function Calendar() { useEffect(() => { - moment.updateLocale('en', { week: { dow: 1 } }) + DateUtils.startWeekFromMonday() + dispatch(changeWindowCalendar(DateUtils.createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) }, []) - const [selectMonthValue, setSelectMonthValue] = useState(() => DateUtils.getCurrentMonth()) - const [selectYearValue, setSelectYearValue] = useState(() => DateUtils.getCurrentYear()) - - const [currentWindowCalendar, setCurrentWindowCalendar] = useState(() => - createAllDaysForCurrWindow(DateUtils.getCurrentYear(), DateUtils.getCurrentMonth()), - ) + const dispatch = useDispatch() + const selectMonthValue = useSelector((state) => state.calendarReducer.selectMonthValue) + const selectYearValue = useSelector((state) => state.calendarReducer.selectYearValue) + const currentWindowCalendar = useSelector((state) => state.calendarReducer.currentWindowCalendar) useEffect(() => { - setCurrentWindowCalendar(createAllDaysForCurrWindow(selectYearValue, selectMonthValue)) + dispatch(changeWindowCalendar(DateUtils.createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) }, [selectMonthValue, selectYearValue]) return (
- - + +
) } export default React.memo(Calendar) - -function createOneDay(newDay, selectMonthValue) { - return { - id: DateUtils.getId(newDay), - date: { - day: DateUtils.getDayOfMonth(newDay), - month: DateUtils.getMonthOfYear(newDay), - year: DateUtils.getYear(newDay), - }, - isWeekend: DateUtils.isWeekend(newDay), - isCurrentMonth: DateUtils.isCurrentMonth(newDay, selectMonthValue), - isToday: DateUtils.isToday(newDay), - } -} - -function createAllDaysForCurrWindow(year, month, day = 1) { - const selectedDay = moment().set({ year: year, month: month, date: day }) - const startDay = selectedDay.clone().startOf('month').startOf('week') - const currDay = startDay.subtract(1, 'day').clone() - const resultArrAllDays = [...Array(42)].map(() => createOneDay(currDay.add(1, 'day').clone(), month)) - - return resultArrAllDays -} diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index f634a2f..7f52e2f 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -4,47 +4,53 @@ import React from 'react' import { Button } from '../../UI/my-button/index' import { Select } from '../../UI/my-select/index' -import { getCurrentMonth, getCurrentYear, getTodayDayId, monthNamesArr, yearsValues } from '../../utils/data' +import { + getCurrentMonth, + getCurrentYear, + getTodayDayId, + monthNamesArr, + yearsValues, + createAllDaysForCurrWindow, +} from '../../utils/data' +import { useDispatch, useSelector } from 'react-redux' +import { changeSelectedDay } from '../../../redux/actions/todos-actions' +import { changeSelectMonth, changeSelectYear, changeWindowCalendar } from '../../../redux/actions/calendar-actions' + +function CalendarNavigation() { + const dispatch = useDispatch() + const selectMonthValue = useSelector((state) => state.calendarReducer.selectMonthValue) + const selectYearValue = useSelector((state) => state.calendarReducer.selectYearValue) -function CalendarNavigation({ - setSelectMonthValue, - setSelectYearValue, - setSelectedDay, - setCurrentWindowCalendar, - createValuesCurrWindow, - selectMonthValue, - selectYearValue, -}) { function onMonthSelectChange(e) { - setSelectMonthValue(Number(e.target.value)) + dispatch(changeSelectMonth(Number(e.target.value))) } function onYearSelectChange(e) { - setSelectYearValue(Number(e.target.value)) + dispatch(changeSelectYear(Number(e.target.value))) } function onTodayClick() { - setSelectMonthValue(() => getCurrentMonth()) - setSelectYearValue(() => getCurrentYear()) - setSelectedDay(() => getTodayDayId()) - setCurrentWindowCalendar(createValuesCurrWindow(getCurrentYear(), getCurrentMonth())) + dispatch(changeSelectYear(getCurrentYear())) + dispatch(changeSelectMonth(getCurrentMonth())) + dispatch(changeSelectedDay(getTodayDayId())) + dispatch(changeWindowCalendar(createAllDaysForCurrWindow(getCurrentYear(), getCurrentMonth()))) } function onNextMonthClick() { if (selectMonthValue === 11) { - setSelectMonthValue(0) - setSelectYearValue((prev) => prev + 1) + dispatch(changeSelectMonth(0)) + dispatch(changeSelectYear(selectYearValue + 1)) } else { - setSelectMonthValue((prev) => prev + 1) + dispatch(changeSelectMonth(selectMonthValue + 1)) } } function onPreviousMonthClick() { if (selectMonthValue === 0) { - setSelectMonthValue(11) - setSelectYearValue((prev) => prev - 1) + dispatch(changeSelectMonth(11)) + dispatch(changeSelectYear(selectYearValue - 1)) } else { - setSelectMonthValue((prev) => prev - 1) + dispatch(changeSelectMonth(selectMonthValue - 1)) } } diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index c8981a0..baaf793 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -2,10 +2,16 @@ import './calendarTable.css' import React from 'react' import { isSelectedDay } from '../../utils/data' +import { useDispatch, useSelector } from 'react-redux' +import { changeSelectedDay } from '../../../redux/actions/todos-actions' -function CalendarTable({ currentWindowCalendar, selectedDay, setSelectedDay, todo }) { - function changeSelectedDay(currDay) { - setSelectedDay(currDay.id) +function CalendarTable({ currentWindowCalendar }) { + const dispatch = useDispatch() + const selectedDay = useSelector((state) => state.todosReducer.selectedDay) + const todo = useSelector((state) => state.todosReducer.todo) + + function onChangeSelectedDay(currDay) { + dispatch(changeSelectedDay(currDay.id)) } return ( @@ -25,7 +31,7 @@ function CalendarTable({ currentWindowCalendar, selectedDay, setSelectedDay, tod return (
{ - changeSelectedDay(currDay) + onChangeSelectedDay(currDay) }} className={'dataItem ' + isWeekendClass(currDay) + IsSelectedDayClass(currDay, selectedDay)} key={currDay.id} diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js index 8a0ac35..9d40dcf 100644 --- a/src/components/Header/Header.js +++ b/src/components/Header/Header.js @@ -5,15 +5,19 @@ import React from 'react' import { Button } from '../UI/my-button/index' import deleteDayTasksSVG from '../../icon/deleteDayTasks.svg' import deleteAllTasksSVG from '../../icon/deleteAllTasks.svg' +import { useDispatch } from 'react-redux' +import { deleteAllTasks, deleteSelectedDayTasks } from '../../redux/actions/todos-actions' + +function Header() { + const dispatch = useDispatch() -function Header({ deleteSelectedDayAllTasks, deleteAllTasks }) { return (
-
diff --git a/src/components/ToDoList/ToDoItem/ToDoItem.js b/src/components/ToDoList/ToDoItem/ToDoItem.js index 049c788..200d7f7 100644 --- a/src/components/ToDoList/ToDoItem/ToDoItem.js +++ b/src/components/ToDoList/ToDoItem/ToDoItem.js @@ -5,11 +5,15 @@ import React, { useCallback, useState } from 'react' import EditTask from './EditTask/EditTask' import ShowTask from './ShowTask/ShowTask' +import { useDispatch } from 'react-redux' +import { updateTask } from '../../../redux/actions/todos-actions' -function ToDoItem({ item, index, deleteTask, updateTask }) { +function ToDoItem({ item, index }) { const [editingId, setEditingId] = useState(null) const [titleChangeInput, setTitleChangeInput] = useState('') + const dispatch = useDispatch() + const editToDo = useCallback((id, title) => { setEditingId(id) setTitleChangeInput(title) @@ -19,6 +23,10 @@ function ToDoItem({ item, index, deleteTask, updateTask }) { setTitleChangeInput(newTitle) }, []) + function onStopDraggable(e, data) { + dispatch(updateTask(item.id, { defaultPos: { x: data.x, y: data.y } })) + } + return (
{ - updateTask(item.id, { defaultPos: { x: data.x, y: data.y } }) + onStopDraggable(e, data) }} >
{editingId === item.id ? ( ) : ( - + )}
diff --git a/src/components/ToDoList/ToDoList.js b/src/components/ToDoList/ToDoList.js index 283a091..c520264 100644 --- a/src/components/ToDoList/ToDoList.js +++ b/src/components/ToDoList/ToDoList.js @@ -3,23 +3,16 @@ import './ToDolist.css' import React from 'react' import ToDoItem from './ToDoItem/ToDoItem' +import { useSelector } from 'react-redux' +import { getSelectedDayTasks } from '../../redux/selectors/todo-selectors' + +function ToDoList() { + const selectedDayTasks = useSelector(getSelectedDayTasks) -function ToDoList({ todo, selectedDay, deleteTask, completedTask, changeTaskTitle, updateTask }) { return (
- {todo[selectedDay]?.length ? ( - todo[selectedDay].map((item, index) => ( - - )) + {selectedDayTasks?.length ? ( + selectedDayTasks.map((item, index) => ) ) : (
Tasks not found
)} diff --git a/src/components/utils/data.js b/src/components/utils/data.js index 27ecbfe..00576a1 100644 --- a/src/components/utils/data.js +++ b/src/components/utils/data.js @@ -5,6 +5,9 @@ export const monthNamesArr = moment()._locale._months export function isSelectedDay(dayObj, selectedDay) { return dayObj.id === selectedDay } +export function startWeekFromMonday() { + moment.updateLocale('en', { week: { dow: 1 } }) +} export function getTodayDayId() { return moment().format('DDMMYYYY') @@ -46,6 +49,29 @@ export function isToday(momentDay) { return momentDay.isSame(moment(), 'day') } +export function createOneDay(newDay, selectMonthValue) { + return { + id: getId(newDay), + date: { + day: getDayOfMonth(newDay), + month: getMonthOfYear(newDay), + year: getYear(newDay), + }, + isWeekend: isWeekend(newDay), + isCurrentMonth: isCurrentMonth(newDay, selectMonthValue), + isToday: isToday(newDay), + } +} + +export function createAllDaysForCurrWindow(year, month, day = 1) { + const selectedDay = moment().set({ year: year, month: month, date: day }) + const startDay = selectedDay.clone().startOf('month').startOf('week') + const currDay = startDay.subtract(1, 'day').clone() + const resultArrAllDays = [...Array(42)].map(() => createOneDay(currDay.add(1, 'day').clone(), month)) + + return resultArrAllDays +} + export const yearsValues = { 2016: 2016, 2017: 2017, diff --git a/src/constants/actions-types/calendar.js b/src/constants/actions-types/calendar.js new file mode 100644 index 0000000..b5e70ad --- /dev/null +++ b/src/constants/actions-types/calendar.js @@ -0,0 +1,3 @@ +export const CHANGE_SELECT_MONTH = 'CHANGE_SELECT_MONTH' +export const CHANGE_SELECT_YEAR = 'CHANGE_SELECT_YEAR' +export const CHANGE_WINDOW_CALENDAR = 'CHANGE_WINDOW_CALENDAR' diff --git a/src/constants/actions-types/index.js b/src/constants/actions-types/index.js new file mode 100644 index 0000000..a8f6238 --- /dev/null +++ b/src/constants/actions-types/index.js @@ -0,0 +1,2 @@ +export * from './todos' +export * from './calendar' diff --git a/src/constants/actions-types/todos.js b/src/constants/actions-types/todos.js new file mode 100644 index 0000000..c9624e4 --- /dev/null +++ b/src/constants/actions-types/todos.js @@ -0,0 +1,8 @@ +export const ADD_TASK = 'ADD_TASK' +export const DELETE_TASK = 'DELETE_TASK' +export const UPDATE_TASK = 'UPDATE_TASK' + +export const DELETE_SELECTED_DAY_TASKS = 'DELETE_SELECTED_DAY_TASKS' +export const DELETE_ALL_TASKS = 'DELETE_ALL_TASKS' + +export const CHANGE_SELECTED_DAY = 'CHANGE_SELECTED_DAY' diff --git a/src/components/utils/constants.js b/src/constants/constants.js similarity index 70% rename from src/components/utils/constants.js rename to src/constants/constants.js index f478153..b1c097c 100644 --- a/src/components/utils/constants.js +++ b/src/constants/constants.js @@ -6,7 +6,3 @@ export const fixSize = { WIDTH_HEADER: 300, WIDTH_CALENDAR: 580, } - -export const Func = () => { - console.log('op') -} diff --git a/src/index.js b/src/index.js index e1d532f..c900898 100644 --- a/src/index.js +++ b/src/index.js @@ -2,5 +2,22 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' +import thunk from 'redux-thunk' +import { createStore, compose, applyMiddleware } from 'redux' +import { rootReducer } from './redux/reducers' +import { Provider } from 'react-redux' + +const store = createStore( + rootReducer, + compose( + applyMiddleware(thunk), + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), //<-- для redux devTools`a + ), +) + const root = ReactDOM.createRoot(document.getElementById('root')) -root.render() +root.render( + + + , +) diff --git a/src/redux/actions/calendar-actions.js b/src/redux/actions/calendar-actions.js new file mode 100644 index 0000000..068c13f --- /dev/null +++ b/src/redux/actions/calendar-actions.js @@ -0,0 +1,22 @@ +import { CHANGE_SELECT_MONTH, CHANGE_SELECT_YEAR, CHANGE_WINDOW_CALENDAR } from '../../constants/actions-types/' + +export function changeSelectMonth(newMonth) { + return { + type: CHANGE_SELECT_MONTH, + data: newMonth, + } +} + +export function changeSelectYear(newYear) { + return { + type: CHANGE_SELECT_YEAR, + data: newYear, + } +} + +export function changeWindowCalendar(newWindowCalendar) { + return { + type: CHANGE_WINDOW_CALENDAR, + data: newWindowCalendar, + } +} diff --git a/src/redux/actions/todos-actions.js b/src/redux/actions/todos-actions.js new file mode 100644 index 0000000..ca4513a --- /dev/null +++ b/src/redux/actions/todos-actions.js @@ -0,0 +1,48 @@ +import { + ADD_TASK, + CHANGE_SELECTED_DAY, + DELETE_ALL_TASKS, + DELETE_SELECTED_DAY_TASKS, + DELETE_TASK, + UPDATE_TASK, +} from '../../constants/actions-types/' + +export function addTask(newTask) { + return { + type: ADD_TASK, + data: { newTask }, + } +} + +export function deleteTask(task) { + return { + type: DELETE_TASK, + data: task, + } +} + +export function updateTask(taskId, changes) { + return { + type: UPDATE_TASK, + data: { taskId, changes }, + } +} + +export function changeSelectedDay(date) { + return { + type: CHANGE_SELECTED_DAY, + data: date, + } +} + +export function deleteSelectedDayTasks() { + return { + type: DELETE_SELECTED_DAY_TASKS, + } +} + +export function deleteAllTasks() { + return { + type: DELETE_ALL_TASKS, + } +} diff --git a/src/redux/reducers/calendar/index.js b/src/redux/reducers/calendar/index.js new file mode 100644 index 0000000..b63f1a1 --- /dev/null +++ b/src/redux/reducers/calendar/index.js @@ -0,0 +1,24 @@ +import * as DateUtils from '../../../components/utils/data' +import { CHANGE_SELECT_MONTH, CHANGE_SELECT_YEAR, CHANGE_WINDOW_CALENDAR } from '../../../constants/actions-types' + +const initialState = { + selectMonthValue: DateUtils.getCurrentMonth(), + selectYearValue: DateUtils.getCurrentYear(), + currentWindowCalendar: [], +} + +export const calendarReducer = (state = initialState, action) => { + switch (action.type) { + case CHANGE_SELECT_MONTH: + return { ...state, selectMonthValue: action.data } + + case CHANGE_SELECT_YEAR: + return { ...state, selectYearValue: action.data } + + case CHANGE_WINDOW_CALENDAR: + return { ...state, currentWindowCalendar: action.data } + + default: + return state + } +} diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js new file mode 100644 index 0000000..a92cc9b --- /dev/null +++ b/src/redux/reducers/index.js @@ -0,0 +1,8 @@ +import { combineReducers } from 'redux' +import { todosReducer } from './todos' +import { calendarReducer } from './calendar' + +export const rootReducer = combineReducers({ + todosReducer, + calendarReducer, +}) diff --git a/src/redux/reducers/todos/index.js b/src/redux/reducers/todos/index.js new file mode 100644 index 0000000..c72fbe2 --- /dev/null +++ b/src/redux/reducers/todos/index.js @@ -0,0 +1,62 @@ +import { + ADD_TASK, + CHANGE_SELECTED_DAY, + DELETE_ALL_TASKS, + DELETE_SELECTED_DAY_TASKS, + DELETE_TASK, + UPDATE_TASK, +} from '../../../constants/actions-types' +import { getTodayDayId } from '../../../components/utils/data' + +const initialState = { + todo: JSON.parse(localStorage.getItem('items')) || {}, + selectedDay: getTodayDayId(), +} + +export const todosReducer = (state = initialState, action) => { + const { todo, selectedDay } = state + switch (action.type) { + case ADD_TASK: { + const { newTask } = action.data + const selectedDayTasks = todo[selectedDay] + const newDayTask = selectedDayTasks ? [...selectedDayTasks, newTask] : [newTask] + + return { ...state, todo: { ...todo, [selectedDay]: newDayTask } } + } + + case DELETE_TASK: { + const task = action.data + const newSelectDayToDo = todo[selectedDay].filter(({ id }) => { + return id !== task.id + }) + + return { ...state, todo: { ...todo, [selectedDay]: newSelectDayToDo } } + } + + case UPDATE_TASK: { + const { taskId, changes } = action.data + const newSelectedDayToDo = todo[selectedDay].map((task) => { + if (task.id !== taskId) { + return task + } + return { ...task, ...changes } + }) + return { ...state, todo: { ...todo, [selectedDay]: newSelectedDayToDo } } + } + + case DELETE_SELECTED_DAY_TASKS: { + return { ...state, todo: { ...todo, [selectedDay]: {} } } + } + + case DELETE_ALL_TASKS: { + return { ...state, todo: {} } + } + + case CHANGE_SELECTED_DAY: { + return { ...state, selectedDay: action.data } + } + + default: + return state + } +} diff --git a/src/redux/selectors/todo-selectors.js b/src/redux/selectors/todo-selectors.js new file mode 100644 index 0000000..62f8c76 --- /dev/null +++ b/src/redux/selectors/todo-selectors.js @@ -0,0 +1,3 @@ +export const getTodo = (state) => state.todosReducer.todo +export const getSelectedDay = (state) => state.todosReducer.selectedDay +export const getSelectedDayTasks = (state) => getTodo(state)[getSelectedDay(state)] From 60c55e778401240205e3ca854b3c6939ce95077a Mon Sep 17 00:00:00 2001 From: andrsvsrg Date: Sat, 24 Sep 2022 16:36:10 +0300 Subject: [PATCH 12/12] add selectors redux --- src/components/Calendar/Calendar.js | 22 +++++++++---------- .../CalendarNavigation/CalendarNavigation.js | 4 ++-- .../Calendar/CalendarTable/CalendarTable.js | 8 ++++--- src/redux/selectors/calendar-selectors.js | 10 +++++++++ src/redux/selectors/todo-selectors.js | 3 +++ 5 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 src/redux/selectors/calendar-selectors.js diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index c61eb9f..6941a2f 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -1,33 +1,31 @@ import './calendar.css' -import moment from 'moment' import React, { useEffect } from 'react' import CalendarNavigation from './CalendarNavigation/CalendarNavigation' import CalendarTable from './CalendarTable/CalendarTable' -import * as DateUtils from '../utils/data' +import { createAllDaysForCurrWindow, startWeekFromMonday } from '../utils/data' import { useDispatch, useSelector } from 'react-redux' import { changeWindowCalendar } from '../../redux/actions/calendar-actions' +import { mapStateCalendarToProps } from '../../redux/selectors/calendar-selectors' function Calendar() { + const dispatch = useDispatch() + const { selectMonthValue, selectYearValue } = useSelector(mapStateCalendarToProps) + useEffect(() => { - DateUtils.startWeekFromMonday() - dispatch(changeWindowCalendar(DateUtils.createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) + startWeekFromMonday() + dispatch(changeWindowCalendar(createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) }, []) - const dispatch = useDispatch() - const selectMonthValue = useSelector((state) => state.calendarReducer.selectMonthValue) - const selectYearValue = useSelector((state) => state.calendarReducer.selectYearValue) - const currentWindowCalendar = useSelector((state) => state.calendarReducer.currentWindowCalendar) - useEffect(() => { - dispatch(changeWindowCalendar(DateUtils.createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) + dispatch(changeWindowCalendar(createAllDaysForCurrWindow(selectYearValue, selectMonthValue))) }, [selectMonthValue, selectYearValue]) return (
- - + +
) } diff --git a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js index 7f52e2f..804acd5 100644 --- a/src/components/Calendar/CalendarNavigation/CalendarNavigation.js +++ b/src/components/Calendar/CalendarNavigation/CalendarNavigation.js @@ -15,11 +15,11 @@ import { import { useDispatch, useSelector } from 'react-redux' import { changeSelectedDay } from '../../../redux/actions/todos-actions' import { changeSelectMonth, changeSelectYear, changeWindowCalendar } from '../../../redux/actions/calendar-actions' +import { mapStateCalendarToProps } from '../../../redux/selectors/calendar-selectors' function CalendarNavigation() { const dispatch = useDispatch() - const selectMonthValue = useSelector((state) => state.calendarReducer.selectMonthValue) - const selectYearValue = useSelector((state) => state.calendarReducer.selectYearValue) + const { selectMonthValue, selectYearValue } = useSelector(mapStateCalendarToProps) function onMonthSelectChange(e) { dispatch(changeSelectMonth(Number(e.target.value))) diff --git a/src/components/Calendar/CalendarTable/CalendarTable.js b/src/components/Calendar/CalendarTable/CalendarTable.js index baaf793..f5cec66 100644 --- a/src/components/Calendar/CalendarTable/CalendarTable.js +++ b/src/components/Calendar/CalendarTable/CalendarTable.js @@ -4,11 +4,13 @@ import React from 'react' import { isSelectedDay } from '../../utils/data' import { useDispatch, useSelector } from 'react-redux' import { changeSelectedDay } from '../../../redux/actions/todos-actions' +import { mapStateToDoToProps } from '../../../redux/selectors/todo-selectors' +import { getWindowCalendar } from '../../../redux/selectors/calendar-selectors' -function CalendarTable({ currentWindowCalendar }) { +function CalendarTable() { const dispatch = useDispatch() - const selectedDay = useSelector((state) => state.todosReducer.selectedDay) - const todo = useSelector((state) => state.todosReducer.todo) + const { todo, selectedDay } = useSelector(mapStateToDoToProps) + const currentWindowCalendar = useSelector(getWindowCalendar) function onChangeSelectedDay(currDay) { dispatch(changeSelectedDay(currDay.id)) diff --git a/src/redux/selectors/calendar-selectors.js b/src/redux/selectors/calendar-selectors.js new file mode 100644 index 0000000..791fcb2 --- /dev/null +++ b/src/redux/selectors/calendar-selectors.js @@ -0,0 +1,10 @@ +export const getSelectMonth = (state) => state.calendarReducer.selectMonthValue +export const getSelectYear = (state) => state.calendarReducer.selectYearValue +export const getWindowCalendar = (state) => state.calendarReducer.currentWindowCalendar +export const mapStateCalendarToProps = (state) => { + return { + selectMonthValue: getSelectMonth(state), + selectYearValue: getSelectYear(state), + currentWindowCalendar: getWindowCalendar(state), + } +} diff --git a/src/redux/selectors/todo-selectors.js b/src/redux/selectors/todo-selectors.js index 62f8c76..4b4228e 100644 --- a/src/redux/selectors/todo-selectors.js +++ b/src/redux/selectors/todo-selectors.js @@ -1,3 +1,6 @@ export const getTodo = (state) => state.todosReducer.todo export const getSelectedDay = (state) => state.todosReducer.selectedDay export const getSelectedDayTasks = (state) => getTodo(state)[getSelectedDay(state)] +export const mapStateToDoToProps = (state) => { + return { todo: getTodo(state), selectedDay: getSelectedDay(state) } +}