├── .gitignore ├── README.md ├── demo.mp4 ├── demo.webm ├── package.json ├── public └── index.html ├── src ├── App.tsx ├── Components │ ├── AddModal │ │ ├── index.tsx │ │ └── styles.ts │ ├── AddTask │ │ ├── index.tsx │ │ └── styles.ts │ ├── Categorie │ │ ├── index.tsx │ │ └── styles.ts │ ├── DeleteModal │ │ ├── index.tsx │ │ └── styles.ts │ ├── ExpandSidebarItem │ │ ├── index.tsx │ │ └── styles.ts │ ├── FilterTag │ │ ├── index.tsx │ │ └── styles.ts │ ├── SidebarItem │ │ ├── index.tsx │ │ └── styles.ts │ └── TaskCard │ │ ├── index.tsx │ │ └── styles.ts ├── Contexts │ ├── addContext.tsx │ ├── addType.ts │ ├── authContext.tsx │ ├── categoriesContext.tsx │ ├── categoriesType.ts │ ├── deleteContext.tsx │ ├── deleteType.ts │ ├── taskListContext.tsx │ └── taskType.ts ├── Img │ ├── Logo.png │ ├── add.svg │ ├── arrow.svg │ ├── edit.svg │ ├── erase.svg │ ├── filter.svg │ ├── folder.svg │ ├── folderFill.svg │ ├── logout.svg │ ├── settings.svg │ ├── settingsFill.svg │ ├── task.png │ └── taskFill.png ├── Pages │ ├── Categorie │ │ ├── index.tsx │ │ └── styles.ts │ ├── Home │ │ ├── index.tsx │ │ └── styles.ts │ └── Login │ │ ├── index.tsx │ │ └── styles.ts ├── Routes │ └── Route.tsx ├── contextProviders.tsx ├── global.ts ├── index.tsx └── react-app-env.d.ts ├── tsconfig.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReactJS-ToDoList 2 | ## Introduction 3 | This project implements the Front-End for a simple To-Do List web application, using the React JS library, and also Styled Components replacing pure CSS.
4 | It includes the login page and the general UI of the app.
5 | The login authentication logic and the tasks database for each user are not implemented, since this project aims to be a Front-End study only. 6 | 7 | ## Demonstration 8 | 9 | 10 | https://user-images.githubusercontent.com/122649188/214991561-d29b14eb-560a-4ba4-aa12-0656278d3fc8.mp4 11 | 12 | 13 | 14 | ## Inspiration 15 | The login page was inspired in [this design](https://dribbble.com/shots/17564792-Log-in-page-Untitled-UI/attachments/12710737?mode=media) by Jordan Hughes. 16 | The home page was inspired in [this design](https://dribbble.com/shots/14440819-KosmoTime-Task-Manager/attachments/6121947?mode=media) by Mik Skuza. 17 | 18 | ## Features 19 | • Login page, including Sign In button, which redirects to the main application;
20 | • Application UI with navigation sidebar and area for the to-do list;
21 | • Add new task, setting name and categorie properties;
22 | • Delete task, with a modal for confirming the action;
23 | • Check task as done via checkbox;
24 | • Filter tasks showing in the to-do list by "done", "not done" or "all";
25 | • Filter tasks showing in the to-do list by their categorie, via selecting on the sidebar;
26 | • Authorization: user cannot access home page before login, neither login page after logged.
27 | 28 | Obs.: currently, the "edit task" and adding or removing categories functionalities are not implemented, since I considered it wouldn't contribute that much to my personal learning, and would be very time consuming. Maybe I'll implement this later on. 29 | 30 | ## Usage 31 | If you want to try this project yourself: 32 | 1. Install Node on your machine, via https://nodejs.org/en/. 33 | 2. Install Yarn on your machine via terminal command: `sudo npm install -g yarn` 34 | 3. Install Git on your machine, via https://git-scm.com/downloads. 35 | 4. Clone this repository to your machine. (more on how to do this [here](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)) 36 | 5. Run ```yarn install``` on the terminal, inside the folder where you downloaded the project, to install all used dependencies. 37 | 6. Run `yarn start` to run the project on your browser. 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /demo.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheusCavini/ReactJS-ToDoList/89d62d130e6e9ae5ad3f58cdda7f6810abcf7a74/demo.mp4 -------------------------------------------------------------------------------- /demo.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheusCavini/ReactJS-ToDoList/89d62d130e6e9ae5ad3f58cdda7f6810abcf7a74/demo.webm -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todolist", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "-": "^0.0.1", 7 | "@testing-library/jest-dom": "^5.14.1", 8 | "@testing-library/react": "^13.0.0", 9 | "@testing-library/user-event": "^13.2.1", 10 | "@types/jest": "^27.0.1", 11 | "@types/node": "^16.7.13", 12 | "@types/react": "^18.0.0", 13 | "@types/react-dom": "^18.0.0", 14 | "D": "^1.0.0", 15 | "gh-pages": "^5.0.0", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0", 18 | "react-router-dom": "^6.7.0", 19 | "react-scripts": "5.0.1", 20 | "react-select": "^5.7.0", 21 | "styled-components": "^5.3.6", 22 | "typescript": "^4.4.2", 23 | "web-vitals": "^2.1.0" 24 | }, 25 | "scripts": { 26 | "start": "react-scripts start", 27 | "build": "react-scripts build", 28 | "test": "react-scripts test", 29 | "eject": "react-scripts eject" 30 | }, 31 | "eslintConfig": { 32 | "extends": [ 33 | "react-app", 34 | "react-app/jest" 35 | ] 36 | }, 37 | "browserslist": { 38 | "production": [ 39 | ">0.2%", 40 | "not dead", 41 | "not op_mini all" 42 | ], 43 | "development": [ 44 | "last 1 chrome version", 45 | "last 1 firefox version", 46 | "last 1 safari version" 47 | ] 48 | }, 49 | "devDependencies": { 50 | "@types/styled-components": "^5.1.26" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | 28 | 29 | 30 | Tasker 31 | 32 | 33 | 34 |
35 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import GlobalStyle from './global' 4 | import ContextProviders from './contextProviders'; 5 | 6 | import { BrowserRouter, Routes, Route } from 'react-router-dom'; 7 | import Login from './Pages/Login'; 8 | import Home from './Pages/Home'; 9 | import CategoriePage from './Pages/Categorie'; 10 | import ProtectedRoute from './Routes/Route'; 11 | 12 | 13 | function App() { 14 | return ( 15 | 16 | 17 | 18 | } /> 19 | } /> 20 | }> 21 | 22 | 23 | 24 | 25 | 26 | ); 27 | } 28 | 29 | export default App; 30 | -------------------------------------------------------------------------------- /src/Components/AddModal/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from "react"; 2 | import * as S from "./styles" 3 | import { AddContext } from "../../Contexts/addContext"; 4 | import { AddType } from "../../Contexts/addType"; 5 | import { TaskListContext } from "../../Contexts/taskListContext"; 6 | import { TaskProps, TaskListType } from "../../Contexts/taskType"; 7 | import { CategoriesContext } from "../../Contexts/categoriesContext"; 8 | import { CategorieContextType } from "../../Contexts/categoriesType"; 9 | import { ActionMeta, InputActionMeta } from "react-select"; 10 | import Select from "react-select/dist/declarations/src/Select"; 11 | 12 | 13 | const AddModal:React.FC =()=>{ 14 | const{ addTask } = useContext(TaskListContext) as TaskListType; 15 | const{categList} = useContext(CategoriesContext) as CategorieContextType; 16 | const{ setShowAdd,} = useContext(AddContext) as AddType; 17 | 18 | 19 | const [taskName, setTaskName ]= useState(""); 20 | const [taskCat, setTaskCat] = useState(categList.findIndex((cat)=>cat.name == "None")); 21 | 22 | function handleTyping(event: React.ChangeEvent){ 23 | setTaskName(event.target.value); 24 | }; 25 | 26 | function handleCancel(){ 27 | setShowAdd(false); 28 | }; 29 | 30 | function handleAdd(){ 31 | const newTask:TaskProps ={ 32 | id: Math.random(), 33 | title: taskName, 34 | categorie: categList[taskCat].name, 35 | color: categList[taskCat].color, 36 | done: false, 37 | } 38 | 39 | setShowAdd(false); 40 | 41 | addTask(newTask); 42 | 43 | } 44 | 45 | var e= document.getElementById("select") as HTMLSelectElement; 46 | 47 | function handleChange(){ 48 | setTaskCat(Number(e.options[(e.selectedIndex)].value)); 49 | } 50 | 51 | 52 | 53 | 54 | 55 | return( 56 | 57 | 58 | Insert name 59 | 60 | Select a categorie 61 | 62 | {categList.map((cat)=>)} 63 | 64 | 65 | Cancel 66 | Add 67 | 68 | 69 | 70 | ) 71 | }; 72 | 73 | export default AddModal; -------------------------------------------------------------------------------- /src/Components/AddModal/styles.ts: -------------------------------------------------------------------------------- 1 | 2 | import styled from "styled-components"; 3 | 4 | export const Background = styled.div` 5 | width:100vw; 6 | height:100vh; 7 | position:fixed; 8 | z-index:3; 9 | display:flex; 10 | align-items:center; 11 | justify-content:center; 12 | background: rgba(0,0,0,0.6); 13 | ` 14 | 15 | export const Container=styled.div` 16 | width: 40vw; 17 | height: 40vh; 18 | background: white; 19 | border-radius:16px; 20 | opacity: 1; 21 | display: flex; 22 | flex-direction:column; 23 | align-items:center; 24 | justify-content: space-between; 25 | padding-top:32px; 26 | 27 | ` 28 | 29 | export const Buttons = styled.div` 30 | height: 80px; 31 | display: flex; 32 | justify-content:space-around; 33 | align-items:center; 34 | ` 35 | 36 | export const CancelButton = styled.button` 37 | background: white; 38 | border: 1px solid blue; 39 | color: blue; 40 | width: 120px; 41 | height: 40px; 42 | border-radius: 8px; 43 | font-size: 20px; 44 | margin: 8px; 45 | 46 | &:hover{ 47 | border:2px solid blue; 48 | font-weight:500; 49 | background: #eee; 50 | } 51 | ` 52 | 53 | export const DeletButton = styled.button` 54 | background: white; 55 | border: 1px solid green; 56 | color:green; 57 | width: 120px; 58 | height: 40px; 59 | border-radius: 8px; 60 | font-size: 20px; 61 | margin: 8px; 62 | 63 | &:hover{ 64 | border:2px solid green; 65 | font-weight:500; 66 | background: #eee; 67 | } 68 | ` 69 | 70 | export const TitleInput = styled.input` 71 | width: 32vw; 72 | height: 40px; 73 | border-radius: 8px; 74 | border: 1px solid #999; 75 | padding-left:8px; 76 | font-size: 20px; 77 | color: #555; 78 | box-sizing: border-box; 79 | 80 | 81 | 82 | &:focus{ 83 | border: 1px solid #999; 84 | outline:none; 85 | } 86 | 87 | &::placeholder{ 88 | color: #bbb; 89 | } 90 | 91 | ` 92 | 93 | export const Select = styled.select` 94 | 95 | width: 32vw; 96 | height: 40px; 97 | border-radius: 8px; 98 | border: 1px solid #999; 99 | padding-left:8px; 100 | font-size: 20px; 101 | color: #555; 102 | box-sizing: border-box; 103 | 104 | &:focus{ 105 | border: 1px solid #999; 106 | outline:none; 107 | } 108 | 109 | &::placeholder{ 110 | color: #bbb; 111 | } 112 | ` 113 | 114 | 115 | export const Text = styled.p` 116 | font-size:20px; 117 | color:#555; 118 | ` 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/Components/AddTask/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import * as S from "./styles"; 3 | import Add from "../../Img/add.svg"; 4 | import { AddType } from "../../Contexts/addType"; 5 | import { AddContext } from "../../Contexts/addContext"; 6 | 7 | const AddTask:React.FC = ()=>{ 8 | const{setShowAdd} = useContext(AddContext) as AddType; 9 | 10 | function handleClick(){ 11 | setShowAdd(true); 12 | }; 13 | 14 | return( 15 | 16 | 17 | Add a task 18 | 19 | ); 20 | }; 21 | 22 | export default AddTask; -------------------------------------------------------------------------------- /src/Components/AddTask/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Container =styled.div` 4 | height: 50px; 5 | width: 70vw; 6 | border: 1px solid #ccc; 7 | border-radius: 16px; 8 | display: flex; 9 | margin: 8px; 10 | box-sizing:border-box; 11 | align-items: center; 12 | justify-content: center; 13 | 14 | &:hover{ 15 | background: #eee; 16 | cursor: pointer; 17 | } 18 | ` 19 | 20 | export const Icon = styled.img` 21 | width:24px; 22 | ` 23 | 24 | export const Text = styled.p` 25 | color: #ccc; 26 | font-size: 20px; 27 | font-weight:400; 28 | margin:16px; 29 | ` -------------------------------------------------------------------------------- /src/Components/Categorie/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as S from "./styles" 3 | import { Link } from "react-router-dom"; 4 | 5 | interface CategorieItemProps{ 6 | name:string; 7 | color:string; 8 | } 9 | 10 | const CategorieItem:React.FC =({name,color})=>{ 11 | 12 | return( 13 | 14 | 15 | 16 | {name} 17 | 18 | 19 | )}; 20 | 21 | export default CategorieItem; -------------------------------------------------------------------------------- /src/Components/Categorie/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | interface ColorTagProps{ 4 | color:string; 5 | } 6 | 7 | export const Categorie = styled.div` 8 | height: 20px; 9 | margin: 4px 0 4px 52px; 10 | display: flex; 11 | align-items: center; 12 | background: #f5f5f5; 13 | ` 14 | 15 | export const ColorTag = styled.div` 16 | height: 14px; 17 | width: 14px; 18 | border-radius: 4px; 19 | background: ${props=> props.color}; 20 | ` 21 | 22 | export const ListName = styled.p` 23 | font-size: 16px; 24 | color: #777; 25 | margin-left:8px; 26 | font-weight:400; 27 | ` -------------------------------------------------------------------------------- /src/Components/DeleteModal/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as S from "./styles"; 3 | import { DeleteType } from "../../Contexts/deleteType"; 4 | import { DeleteContext } from "../../Contexts/deleteContext"; 5 | import { useContext } from "react"; 6 | import { TaskListContext } from "../../Contexts/taskListContext"; 7 | import { TaskListType } from "../../Contexts/taskType"; 8 | 9 | 10 | 11 | 12 | const DeleteModal:React.FC =()=>{ 13 | const { setShowDelete, id, setId }= useContext(DeleteContext) as DeleteType; 14 | const{deleteTask} = useContext(TaskListContext) as TaskListType; 15 | 16 | function handleCancel(){ 17 | setShowDelete(false); 18 | }; 19 | 20 | function handleConfirm(){ 21 | deleteTask(id); 22 | setId(0); 23 | setShowDelete(false); 24 | 25 | } 26 | 27 | 28 | return( 29 | 30 | 31 | Are you sure you want to delete this task? 32 | 33 | Cancel 34 | Delete 35 | 36 | 37 | 38 | ) 39 | }; 40 | 41 | export default DeleteModal; -------------------------------------------------------------------------------- /src/Components/DeleteModal/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | 4 | export const Background = styled.div` 5 | width:100vw; 6 | height:100vh; 7 | position:fixed; 8 | z-index:3; 9 | display:flex; 10 | align-items:center; 11 | justify-content:center; 12 | background: rgba(0,0,0,0.6); 13 | ` 14 | 15 | export const Container=styled.div` 16 | width: 25vw; 17 | height: 25vh; 18 | background: white; 19 | border-radius:16px; 20 | opacity: 1; 21 | display: flex; 22 | flex-direction:column; 23 | align-items:center; 24 | justify-content: space-between; 25 | 26 | ` 27 | 28 | export const Text = styled.p` 29 | font-size:24px; 30 | color: #555; 31 | wrap: wrap; 32 | text-align:center; 33 | padding:20px; 34 | ` 35 | 36 | export const Buttons = styled.div` 37 | height: 80px; 38 | display: flex; 39 | justify-content:space-around; 40 | align-items:center; 41 | ` 42 | 43 | export const CancelButton = styled.button` 44 | background: white; 45 | border: 1px solid blue; 46 | color: blue; 47 | width: 120px; 48 | height: 40px; 49 | border-radius: 8px; 50 | font-size: 20px; 51 | margin: 8px; 52 | 53 | &:hover{ 54 | border:2px solid blue; 55 | font-weight:500; 56 | background: #eee; 57 | } 58 | ` 59 | 60 | export const DeletButton = styled.button` 61 | background: white; 62 | border: 1px solid red; 63 | color:red; 64 | width: 120px; 65 | height: 40px; 66 | border-radius: 8px; 67 | font-size: 20px; 68 | margin: 8px; 69 | 70 | &:hover{ 71 | border:2px solid red; 72 | font-weight:500; 73 | background: #eee; 74 | } 75 | 76 | ` -------------------------------------------------------------------------------- /src/Components/ExpandSidebarItem/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useContext} from "react"; 2 | import * as S from "./styles" 3 | import Arrow from "../../Img/arrow.svg" 4 | import CategorieItem from "../Categorie"; 5 | import Add from "../../Img/add.svg"; 6 | import { CategoriesContext } from "../../Contexts/categoriesContext"; 7 | import { CategorieContextType } from "../../Contexts/categoriesType"; 8 | 9 | interface SidebarItemProps{ 10 | name: string; 11 | icon: string; 12 | 13 | } 14 | 15 | 16 | 17 | const ExpandSidebarItem:React.FC =({name, icon})=>{ 18 | const [active, setActive] = useState(false); 19 | const {categList}= useContext(CategoriesContext) as CategorieContextType; 20 | 21 | function handleActivate(){ 22 | setActive(!active); 23 | } 24 | 25 | return( 26 | 27 | 28 | 29 | {name} 30 | 31 | 32 | 33 | {categList.map(cat=>)} 34 | 35 | 36 | Add new 37 | 38 | 39 | 40 | 41 | ); 42 | }; 43 | 44 | 45 | export default ExpandSidebarItem; -------------------------------------------------------------------------------- /src/Components/ExpandSidebarItem/styles.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import { css } from "styled-components"; 4 | 5 | interface ContainerProps{ 6 | isActive: boolean; 7 | } 8 | 9 | 10 | export const Name = styled.h3` 11 | font-size:16px; 12 | font-weight:500; 13 | ` 14 | export const OuterContainer = styled.div` 15 | height: auto; 16 | width: 15vw; 17 | border-radius: 18 | display: flex; 19 | flex-direction:column; 20 | align-items:center; 21 | justify-content: top; 22 | color:#777; 23 | font-weight:100; 24 | margin: 4px 0; 25 | 26 | border-radius:8px; 27 | 28 | ${props => 29 | props.isActive && 30 | css` 31 | background: #f5f5f5; 32 | `}; 33 | margin: 0; 34 | ` 35 | 36 | export const Container = styled.div` 37 | height: 40px; 38 | width: 15vw; 39 | border-radius:8px; 40 | display: flex; 41 | align-items:center; 42 | justify-content: left; 43 | color:#777; 44 | font-weight:100; 45 | ${props => 46 | props.isActive && 47 | css` 48 | background: #f5f5f5; 49 | `}; 50 | margin: 0; 51 | 52 | &:hover{ 53 | cursor:pointer; 54 | ${props => 55 | props.isActive ? 56 | css` 57 | background: #f5f5f5; 58 | `: css` 59 | background: #fafafa; 60 | `}; 61 | } 62 | 63 | ` 64 | 65 | 66 | 67 | export const Icon = styled.img` 68 | width: 20px; 69 | margin: 8px 16px; 70 | ` 71 | 72 | export const Arrow = styled.img` 73 | width: 14px; 74 | margin: 8px 16px; 75 | 76 | ${props => 77 | props.isActive && 78 | css` 79 | transform:rotate(180deg); 80 | `}; 81 | margin: 4px 24px; 82 | ` 83 | 84 | export const CatArea = styled.div` 85 | display: flex; 86 | width:15vw; 87 | height: auto; 88 | background: #f5f5f5; 89 | border-radius:8px; 90 | flex-direction:column; 91 | padding-bottom: 8px; 92 | 93 | ${props => 94 | !props.isActive && 95 | css` 96 | display:none; 97 | `}; 98 | 99 | ` 100 | 101 | export const AddArea = styled.div` 102 | height: 20px; 103 | margin: 4px 0 4px 52px; 104 | display: flex; 105 | align-items: center; 106 | background: #f5f5f5; 107 | ` 108 | 109 | 110 | export const AddText = styled.p` 111 | font-size: 16px; 112 | color: #ccc; 113 | margin-left:8px; 114 | font-weight:400; 115 | ` 116 | 117 | export const AddIcon = styled.img` 118 | height: 16px; 119 | ` 120 | 121 | 122 | -------------------------------------------------------------------------------- /src/Components/FilterTag/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as S from "./styles"; 3 | 4 | 5 | interface tagProps { 6 | name:string; 7 | active:boolean; 8 | } 9 | 10 | 11 | const FilterTag:React.FC =({name, active})=>{ 12 | return ( 13 | 14 | {name} 15 | 16 | ); 17 | } 18 | 19 | export default FilterTag; -------------------------------------------------------------------------------- /src/Components/FilterTag/styles.ts: -------------------------------------------------------------------------------- 1 | import styled, {css} from "styled-components"; 2 | 3 | interface activeProps{ 4 | active: boolean; 5 | } 6 | 7 | export const Container = styled.div` 8 | width: 80px; 9 | height: 24px; 10 | border-radius:8px; 11 | border: 1px solid #ccc; 12 | display: flex; 13 | align-items:center; 14 | justify-content:center; 15 | margin:0 2px; 16 | 17 | &:hover{ 18 | cursor:pointer; 19 | background: #eee; 20 | } 21 | 22 | ${props => props.active && css` 23 | background: white; 24 | border:0; 25 | box-shadow: 0 1px 2px #ccc; 26 | ` } 27 | ` 28 | 29 | export const TagName = styled.h3` 30 | font-size: 16px; 31 | color:#ccc; 32 | 33 | ${props => props.active && css` 34 | color: #333; 35 | ` } 36 | ` -------------------------------------------------------------------------------- /src/Components/SidebarItem/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import * as S from "./styles" 3 | 4 | interface SidebarItemProps{ 5 | name: string; 6 | icon: string; 7 | isActive: boolean; 8 | } 9 | 10 | const SidebarItem:React.FC =({name, icon, isActive})=>{ 11 | return( 12 | 13 | 14 | {name} 15 | 16 | ); 17 | }; 18 | 19 | 20 | export default SidebarItem; -------------------------------------------------------------------------------- /src/Components/SidebarItem/styles.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import { css } from "styled-components"; 4 | 5 | interface ContainerProps{ 6 | isActive: boolean; 7 | } 8 | 9 | 10 | export const Name = styled.h3` 11 | font-size:16px; 12 | font-weight:500; 13 | ` 14 | 15 | export const Container = styled.div` 16 | height: 40px; 17 | width: 15vw; 18 | border-radius:8px; 19 | display: flex; 20 | align-items:center; 21 | justify-content: left; 22 | color:#777; 23 | font-weight:100; 24 | ${props => 25 | props.isActive && 26 | css` 27 | background: #f5f5f5; 28 | color:#7f56da; 29 | `}; 30 | margin: 4px 0; 31 | 32 | &:hover{ 33 | cursor:pointer; 34 | ${props => 35 | props.isActive ? 36 | css` 37 | background: #f5f5f5; 38 | `: css` 39 | background: #fafafa; 40 | `}; 41 | } 42 | 43 | ` 44 | 45 | 46 | 47 | export const Icon = styled.img` 48 | width: 20px; 49 | margin: 8px 16px; 50 | ` 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/Components/TaskCard/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useContext} from "react"; 2 | import * as S from "./styles"; 3 | import Edit from "../../Img/edit.svg"; 4 | import Erase from "../../Img/erase.svg"; 5 | import { TaskListContext } from "../../Contexts/taskListContext"; 6 | import { TaskListType } from "../../Contexts/taskType"; 7 | import { DeleteContext } from "../../Contexts/deleteContext"; 8 | import { DeleteType } from "../../Contexts/deleteType"; 9 | 10 | 11 | 12 | interface TaskCardProps{ 13 | id:number; 14 | name: string; 15 | list: string; 16 | color: string; 17 | done: boolean; 18 | }; 19 | 20 | const TaskCard: React.FC =({id, name,list, color, done})=>{ 21 | 22 | const{setShowDelete,setId} = useContext(DeleteContext) as DeleteType; 23 | const{checkTask} = useContext(TaskListContext) as TaskListType; 24 | 25 | function handleCheck(){ 26 | checkTask(id); 27 | } 28 | 29 | function handleDelete(){ 30 | setShowDelete(true); 31 | setId(id); 32 | } 33 | 34 | return( 35 | 36 | 37 | 38 | 39 | 40 | {name} 41 | 42 | 43 | {list} 44 | 45 | 46 | 47 | 48 | 49 | ); 50 | }; 51 | 52 | export default TaskCard; -------------------------------------------------------------------------------- /src/Components/TaskCard/styles.ts: -------------------------------------------------------------------------------- 1 | import styled, {css} from "styled-components"; 2 | 3 | interface ColorTagProps{ 4 | color:string; 5 | } 6 | 7 | interface DoneProps{ 8 | done:boolean; 9 | } 10 | 11 | export const Container =styled.div` 12 | height: 80px; 13 | width: 70vw; 14 | background: white; 15 | border-radius: 16px; 16 | box-shadow: 0 3px 3px #ccc; 17 | display: flex; 18 | margin: 8px; 19 | box-sizing:border-box; 20 | ` 21 | export const Name = styled.h2` 22 | font-size: 22px; 23 | color: #555; 24 | margin: 8px 16px; 25 | font-weight:500; 26 | 27 | ${props => props.done && 28 | css` 29 | color:#bbb; 30 | font-weight:400; 31 | text-decoration: line-through;`} 32 | ` 33 | export const Icon = styled.img` 34 | width: 24px; 35 | margin: 24px; 36 | background: white; 37 | 38 | &:hover{ 39 | cursor:pointer; 40 | } 41 | ` 42 | export const CheckField = styled.div` 43 | width: 80px; 44 | height: 80px; 45 | border-right: 2px solid #eee ; 46 | display: flex; 47 | align-items:center; 48 | justify-content:center; 49 | ` 50 | export const Description = styled.div` 51 | height: 80px; 52 | width: 50vw; 53 | padding: 6px 8px; 54 | box-sizing: border-box; 55 | ` 56 | export const ListBelong = styled.div` 57 | height: 20px; 58 | margin: 0 16px; 59 | display: flex; 60 | align-items: center; 61 | ` 62 | 63 | export const ColorTag = styled.div` 64 | height: 16px; 65 | width: 16px; 66 | border-radius: 6px; 67 | background: ${props=> props.color}; 68 | ` 69 | 70 | export const ListName = styled.p` 71 | font-size: 16px; 72 | color: #999; 73 | margin-left:8px; 74 | font-weight:400; 75 | ` 76 | 77 | export const InvisibleCheck = styled.input.attrs({type:'checkbox'})` 78 | display: none; 79 | ` 80 | 81 | export const CheckboxRing = styled.div` 82 | background: white; 83 | height: 24px; 84 | width: 24px; 85 | border: 1px solid #7f56da; 86 | border-radius:12px; 87 | display: flex; 88 | align-items: center; 89 | justify-content: center; 90 | 91 | &:hover{ 92 | cursor: pointer; 93 | } 94 | 95 | ` 96 | export const CheckFill = styled.div` 97 | background: #7f56da; 98 | height: 20px; 99 | width: 20px; 100 | border-radius:10px; 101 | ${props => !props.done && 102 | css`display:none;`} 103 | ` -------------------------------------------------------------------------------- /src/Contexts/addContext.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, createContext, ReactNode} from "react"; 2 | import { AddType } from "./addType"; 3 | 4 | export interface ChildrenProps { 5 | children: React.ReactNode; 6 | } 7 | 8 | export const AddContext = createContext(null); 9 | 10 | export const AddContextProvider: React.FC = ({children}) =>{ 11 | const [showAdd, setShowAdd] = useState(false); 12 | const [id, setId] = useState(0); 13 | 14 | return( 15 | 16 | {children} 17 | 18 | ); 19 | 20 | } -------------------------------------------------------------------------------- /src/Contexts/addType.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | 4 | 5 | export type AddType ={ 6 | showAdd:boolean; 7 | setShowAdd: Function; 8 | id: number; 9 | setId: Function; 10 | } -------------------------------------------------------------------------------- /src/Contexts/authContext.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, createContext} from "react"; 2 | import { ChildrenProps } from "./deleteContext"; 3 | 4 | export interface UserDataProps{ 5 | email: string, 6 | } 7 | 8 | export type AuthType = { 9 | userData: UserDataProps, 10 | setUserData: Function 11 | } 12 | 13 | const AuthContext = createContext(null); 14 | 15 | export const AuthProvider:React.FC = ({ children }) => { 16 | 17 | const [userData, setUserData] = useState(() => { 18 | const email = localStorage.getItem('@Project:email'); 19 | 20 | if (email) { 21 | return { email: JSON.parse(email) }; 22 | }else{ 23 | return {email:""} }; 24 | }); 25 | 26 | return( 27 | 28 | {children} 29 | 30 | ); 31 | 32 | } 33 | 34 | export default AuthContext; -------------------------------------------------------------------------------- /src/Contexts/categoriesContext.tsx: -------------------------------------------------------------------------------- 1 | import React, {createContext, useState, ReactNode} from "react"; 2 | import { CategorieProps, CategorieContextType } from "./categoriesType"; 3 | 4 | interface ChildrenProps { 5 | children: React.ReactNode; 6 | }; 7 | 8 | export const CategoriesContext = createContext(null); 9 | 10 | export const CategoriesContextProvider:React.FC = ({children})=>{ 11 | 12 | const [categList, setCategList] = useState([ 13 | { 14 | id:0, 15 | name: "None", 16 | color: "#afafaf" 17 | }, 18 | { 19 | id:1, 20 | name: "Home", 21 | color: "#FF9C9C" 22 | }, 23 | { id:2, 24 | name:"School", 25 | color: "#FFD79C" 26 | }, 27 | { 28 | id:3, 29 | name:"Shopping list", 30 | color: "#9CD0FF" 31 | }, 32 | ]) 33 | 34 | return( 35 | 36 | {children} 37 | 38 | ) 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /src/Contexts/categoriesType.ts: -------------------------------------------------------------------------------- 1 | export interface CategorieProps{ 2 | id:number; 3 | name:string; 4 | color:string; 5 | }; 6 | 7 | export type CategorieContextType = { 8 | categList: CategorieProps[]; 9 | 10 | } -------------------------------------------------------------------------------- /src/Contexts/deleteContext.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, createContext, ReactNode} from "react"; 2 | import { DeleteType } from "./deleteType"; 3 | 4 | export interface ChildrenProps { 5 | children: React.ReactNode; 6 | 7 | } 8 | 9 | export const DeleteContext = createContext(null); 10 | 11 | export const DeleteContextProvider: React.FC = ({children}) =>{ 12 | const [showDelete, setShowDelete] = useState(false); 13 | const [id, setId] = useState(0); 14 | 15 | return( 16 | 17 | {children} 18 | 19 | ); 20 | 21 | } -------------------------------------------------------------------------------- /src/Contexts/deleteType.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | 4 | 5 | export type DeleteType ={ 6 | showDelete:boolean; 7 | setShowDelete: Function; 8 | id: number; 9 | setId: Function; 10 | } -------------------------------------------------------------------------------- /src/Contexts/taskListContext.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, createContext, ReactNode} from "react"; 2 | import { TaskProps, TaskListType } from "./taskType"; 3 | 4 | interface ChildrenProps { 5 | children: React.ReactNode; 6 | } 7 | 8 | export const TaskListContext = createContext(null); 9 | 10 | export const TaskListContextProvider: React.FC = ({children}) =>{ 11 | const [taskList, setTaskList] = useState([ 12 | { 13 | id:1, 14 | title: "Example task", 15 | done: false, 16 | categorie: "Home", 17 | color: "#FF9C9C", 18 | }, 19 | { 20 | id:2, 21 | title: "Example task 2", 22 | done: false, 23 | categorie: "Home", 24 | color: "#FF9C9C", 25 | }, 26 | { 27 | id:3, 28 | title: "Example task 3", 29 | done: true, 30 | categorie: "Home", 31 | color: "#FF9C9C", 32 | }, 33 | 34 | ]); 35 | const [doneTasks, setDoneTasks]= useState(taskList.filter((task:TaskProps) => task.done==true)); 36 | const [notDoneTasks, setNotDoneTasks] = useState(taskList.filter((task:TaskProps) => task.done==false)); 37 | 38 | const addTask = (task: TaskProps)=>{ 39 | 40 | taskList.push(task) 41 | setTaskList([...taskList]); 42 | console.log(taskList) 43 | setNotDoneTasks([...notDoneTasks, task]); 44 | 45 | 46 | }; 47 | 48 | const checkTask = (id:number)=>{ 49 | taskList.filter((task: TaskProps) => { 50 | if (task.id === id) { 51 | task.done = !task.done 52 | setTaskList([...taskList]); 53 | setDoneTasks(taskList.filter((task:TaskProps) => task.done==true)); 54 | setNotDoneTasks(taskList.filter((task:TaskProps) => task.done!=true)); 55 | } 56 | }); 57 | }; 58 | 59 | const deleteTask = (id:number)=>{ 60 | const index = taskList.findIndex((task:TaskProps)=>task.id == id); 61 | taskList.splice(index,1); 62 | setTaskList([...taskList]); 63 | console.log(taskList); 64 | setDoneTasks(taskList.filter((task:TaskProps) => task.done==true)); 65 | setNotDoneTasks(taskList.filter((task:TaskProps) => task.done!=true)); 66 | }; 67 | 68 | return( 69 | 70 | {children} 71 | 72 | ) 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/Contexts/taskType.ts: -------------------------------------------------------------------------------- 1 | export interface TaskProps{ 2 | id:number; 3 | title: string; 4 | done:boolean; 5 | categorie: string; 6 | color: string; 7 | }; 8 | 9 | export type TaskListType = { 10 | taskList: TaskProps[]; 11 | doneTasks: TaskProps[]; 12 | notDoneTasks: TaskProps[]; 13 | addTask:(task: TaskProps)=>void; 14 | checkTask: (id:number) =>void; 15 | deleteTask: (id:number)=>void; 16 | } -------------------------------------------------------------------------------- /src/Img/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheusCavini/ReactJS-ToDoList/89d62d130e6e9ae5ad3f58cdda7f6810abcf7a74/src/Img/Logo.png -------------------------------------------------------------------------------- /src/Img/add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/erase.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/filter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Img/folderFill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/settings.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/Img/settingsFill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Img/task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheusCavini/ReactJS-ToDoList/89d62d130e6e9ae5ad3f58cdda7f6810abcf7a74/src/Img/task.png -------------------------------------------------------------------------------- /src/Img/taskFill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MatheusCavini/ReactJS-ToDoList/89d62d130e6e9ae5ad3f58cdda7f6810abcf7a74/src/Img/taskFill.png -------------------------------------------------------------------------------- /src/Pages/Categorie/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useContext, useState} from "react"; 2 | 3 | import {useParams} from "react-router-dom"; 4 | 5 | import * as S from "./styles"; 6 | import Logo from "../../Img/Logo.png" 7 | import TaskFill from "../../Img/task.png"; 8 | import Settings from "../../Img/settings.svg"; 9 | import Folder from "../../Img/folder.svg"; 10 | import Logout from "../../Img/logout.svg" 11 | import SidebarItem from "../../Components/SidebarItem"; 12 | import ExpandSidebarItem from "../../Components/ExpandSidebarItem"; 13 | import TaskCard from "../../Components/TaskCard"; 14 | import AddTask from "../../Components/AddTask"; 15 | import { TaskListContext } from "../../Contexts/taskListContext"; 16 | import { TaskListType } from "../../Contexts/taskType"; 17 | import FilterTag from "../../Components/FilterTag"; 18 | import Filter from "../../Img/filter.svg"; 19 | import { DeleteContext } from "../../Contexts/deleteContext"; 20 | import { DeleteType } from "../../Contexts/deleteType"; 21 | import DeleteModal from "../../Components/DeleteModal"; 22 | import AddModal from "../../Components/AddModal"; 23 | import { AddContext } from "../../Contexts/addContext"; 24 | import { AddType } from "../../Contexts/addType"; 25 | import { Link } from "react-router-dom"; 26 | import AuthContext, {AuthType, UserDataProps} from "../../Contexts/authContext"; 27 | 28 | 29 | const CategoriePage:React.FC = ()=>{ 30 | const {name} = useParams() 31 | 32 | const{taskList, doneTasks, notDoneTasks} = useContext(TaskListContext) as TaskListType; 33 | const{showDelete} = useContext(DeleteContext) as DeleteType; 34 | const{showAdd} = useContext(AddContext) as AddType; 35 | const [listToDisplay, setListToDisplay] = useState(0); 36 | const listOfLists = [ 37 | taskList.filter(task => task.categorie==name), 38 | doneTasks.filter(task => task.categorie==name), 39 | notDoneTasks.filter(task => task.categorie==name)]; 40 | 41 | const [allActive, setAllActive] = useState(true); 42 | const [doneActive, setDoneActive] = useState(false); 43 | const [notDoneActive, setNotDoneActive] = useState(false); 44 | 45 | const {setUserData} = useContext(AuthContext) as AuthType; 46 | 47 | 48 | 49 | function handleAll(){ 50 | setListToDisplay(0); 51 | setAllActive(true); 52 | setDoneActive(false); 53 | setNotDoneActive(false); 54 | }; 55 | 56 | function handleDone(){ 57 | setListToDisplay(1); 58 | setAllActive(false); 59 | setDoneActive(true); 60 | setNotDoneActive(false); 61 | }; 62 | function handleNotDone(){ 63 | setListToDisplay(2); 64 | setAllActive(false); 65 | setDoneActive(false); 66 | setNotDoneActive(true); 67 | }; 68 | 69 | function handleLogout(){ 70 | localStorage.removeItem('@Project:email'); 71 | setUserData({email:""}); 72 | }; 73 | return( 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | {name} 92 | 93 | Tasks 94 | 95 |
96 |
97 |
98 | 99 |
100 |
101 | {listOfLists[listToDisplay].map(task =>)} 102 | 103 |
104 | {showDelete && } 105 | {showAdd && } 106 |
107 | 108 | 109 | ); 110 | }; 111 | 112 | export default CategoriePage; -------------------------------------------------------------------------------- /src/Pages/Categorie/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Page = styled.div` 4 | width: 100vw; 5 | height: 100vh; 6 | display: flex; 7 | flex: row; 8 | background-color: #f5f5f5; 9 | ` 10 | 11 | export const Sidebar = styled.div` 12 | height: 100vh; 13 | width: 18vw; 14 | background-color: white; 15 | display: flex; 16 | flex-direction:column; 17 | align-items: center; 18 | justify-content: space-between; 19 | padding: 8px 0; 20 | box-sizing: border-box; 21 | ` 22 | export const Img = styled.img` 23 | width: 50px; 24 | margin:32px; 25 | ` 26 | 27 | export const Tabs = styled.div` 28 | display: flex; 29 | flex-direction: column; 30 | align-items:center; 31 | height: 60vh; 32 | ` 33 | export const Main = styled.div` 34 | height: 100vh; 35 | width: 82vw; 36 | display: flex; 37 | flex-direction: column; 38 | align-items:center; 39 | justify-content: start; 40 | overflow-y:scroll; 41 | ` 42 | 43 | export const Header = styled.h1` 44 | font-size: 40px; 45 | font-weight:400; 46 | color: #555; 47 | margin: 16px; 48 | ` 49 | 50 | export const TitleAndFilter = styled.div` 51 | height: 20px; 52 | width: 70vw; 53 | display: flex; 54 | justify-content: space-between; 55 | align-items: center; 56 | margin-top:16px; 57 | margin-bottom:4px; 58 | ` 59 | 60 | export const Title = styled.h3` 61 | font-size: 24px; 62 | color:#555; 63 | ` 64 | 65 | export const FilterField = styled.div` 66 | height: 20px; 67 | display: flex; 68 | justify-content:center;; 69 | ` 70 | 71 | export const FilterIcon = styled.img` 72 | height: 20px; 73 | margin: 0 8px; 74 | ` -------------------------------------------------------------------------------- /src/Pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useContext, useState} from "react"; 2 | import * as S from "./styles"; 3 | import Logo from "../../Img/Logo.png" 4 | import TaskFill from "../../Img/taskFill.png"; 5 | import Settings from "../../Img/settings.svg"; 6 | import Folder from "../../Img/folder.svg"; 7 | import Logout from "../../Img/logout.svg" 8 | import SidebarItem from "../../Components/SidebarItem"; 9 | import ExpandSidebarItem from "../../Components/ExpandSidebarItem"; 10 | import TaskCard from "../../Components/TaskCard"; 11 | import AddTask from "../../Components/AddTask"; 12 | import { TaskListContext } from "../../Contexts/taskListContext"; 13 | import { TaskListType } from "../../Contexts/taskType"; 14 | import FilterTag from "../../Components/FilterTag"; 15 | import Filter from "../../Img/filter.svg"; 16 | import { DeleteContext } from "../../Contexts/deleteContext"; 17 | import { DeleteType } from "../../Contexts/deleteType"; 18 | import DeleteModal from "../../Components/DeleteModal"; 19 | import AddModal from "../../Components/AddModal"; 20 | import { AddContext } from "../../Contexts/addContext"; 21 | import { AddType } from "../../Contexts/addType"; 22 | import { Link } from "react-router-dom"; 23 | import AuthContext, {AuthType, UserDataProps} from "../../Contexts/authContext"; 24 | 25 | 26 | const Home:React.FC = ()=>{ 27 | const{taskList, doneTasks, notDoneTasks} = useContext(TaskListContext) as TaskListType; 28 | const{showDelete} = useContext(DeleteContext) as DeleteType; 29 | const{showAdd} = useContext(AddContext) as AddType; 30 | const [listToDisplay, setListToDisplay] = useState(0); 31 | const listOfLists = [taskList, doneTasks, notDoneTasks]; 32 | 33 | const [allActive, setAllActive] = useState(true); 34 | const [doneActive, setDoneActive] = useState(false); 35 | const [notDoneActive, setNotDoneActive] = useState(false); 36 | 37 | const {setUserData} = useContext(AuthContext) as AuthType; 38 | 39 | 40 | 41 | function handleAll(){ 42 | setListToDisplay(0); 43 | setAllActive(true); 44 | setDoneActive(false); 45 | setNotDoneActive(false); 46 | }; 47 | 48 | function handleDone(){ 49 | setListToDisplay(1); 50 | setAllActive(false); 51 | setDoneActive(true); 52 | setNotDoneActive(false); 53 | }; 54 | function handleNotDone(){ 55 | setListToDisplay(2); 56 | setAllActive(false); 57 | setDoneActive(false); 58 | setNotDoneActive(true); 59 | }; 60 | 61 | function handleLogout(){ 62 | localStorage.removeItem('@Project:email'); 63 | setUserData({email:""}); 64 | }; 65 | return( 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | All your tasks 82 | 83 | Tasks 84 | 85 |
86 |
87 |
88 | 89 |
90 |
91 | {listOfLists[listToDisplay].map(task =>)} 92 | 93 |
94 | {showDelete && } 95 | {showAdd && } 96 |
97 | 98 | 99 | ); 100 | }; 101 | 102 | export default Home; -------------------------------------------------------------------------------- /src/Pages/Home/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Page = styled.div` 4 | width: 100vw; 5 | height: 100vh; 6 | display: flex; 7 | flex: row; 8 | background-color: #f5f5f5; 9 | ` 10 | 11 | export const Sidebar = styled.div` 12 | height: 100vh; 13 | width: 18vw; 14 | background-color: white; 15 | display: flex; 16 | flex-direction:column; 17 | align-items: center; 18 | justify-content: space-between; 19 | padding: 8px 0; 20 | box-sizing: border-box; 21 | ` 22 | export const Img = styled.img` 23 | width: 50px; 24 | margin:32px; 25 | ` 26 | 27 | export const Tabs = styled.div` 28 | display: flex; 29 | flex-direction: column; 30 | align-items:center; 31 | height: 60vh; 32 | ` 33 | export const Main = styled.div` 34 | height: 100vh; 35 | width: 82vw; 36 | display: flex; 37 | flex-direction: column; 38 | align-items:center; 39 | justify-content: start; 40 | overflow-y:scroll; 41 | ` 42 | 43 | export const Header = styled.h1` 44 | font-size: 40px; 45 | font-weight:400; 46 | color: #555; 47 | margin: 16px; 48 | ` 49 | 50 | export const TitleAndFilter = styled.div` 51 | height: 20px; 52 | width: 70vw; 53 | display: flex; 54 | justify-content: space-between; 55 | align-items: center; 56 | margin-top:16px; 57 | margin-bottom:4px; 58 | ` 59 | 60 | export const Title = styled.h3` 61 | font-size: 24px; 62 | color:#555; 63 | ` 64 | 65 | export const FilterField = styled.div` 66 | height: 20px; 67 | display: flex; 68 | justify-content:center;; 69 | ` 70 | 71 | export const FilterIcon = styled.img` 72 | height: 20px; 73 | margin: 0 8px; 74 | ` -------------------------------------------------------------------------------- /src/Pages/Login/index.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useContext} from "react"; 2 | import * as S from "./styles"; 3 | import Logo from "../../Img/Logo.png"; 4 | import { Link } from "react-router-dom"; 5 | import AuthContext, {AuthType} from "../../Contexts/authContext"; 6 | 7 | 8 | const Login: React.FC = ()=>{ 9 | const {setUserData} = useContext(AuthContext) as AuthType; 10 | const [email, setEmail] = useState(""); 11 | 12 | function handleLogin(){ 13 | localStorage.setItem('@Project:email', email); 14 | setUserData({email}) 15 | 16 | 17 | } 18 | 19 | 20 | 21 | function handleEmail(event: React.ChangeEvent){ 22 | setEmail(event.target.value) 23 | } 24 | 25 | return( 26 | 27 | 28 | 29 | 30 | 31 | Welcome to Tasker 32 | Please, insert your informations to access your tasks. 33 | Email 34 | 35 | Password 36 | 37 | Remember me 38 | 39 | Sign In 40 | 41 | Don't have an account? Sign Up 42 | 43 | 44 | ) 45 | }; 46 | 47 | export default Login; -------------------------------------------------------------------------------- /src/Pages/Login/styles.ts: -------------------------------------------------------------------------------- 1 | 2 | import styled from 'styled-components'; 3 | 4 | export const Img = styled.img` 5 | width: 30vw; 6 | ` 7 | 8 | export const Page = styled.div` 9 | width: 100vw; 10 | height: 100vh; 11 | display: flex; 12 | flex: row; 13 | ` 14 | 15 | export const LeftSide = styled.div` 16 | width: 50vw; 17 | height: 100vh; 18 | background-color: #eee; 19 | display: flex; 20 | align-items:center; 21 | justify-content:center; 22 | ` 23 | 24 | export const RightSide = styled.div` 25 | width: 50vw; 26 | height: 100vh; 27 | display: flex; 28 | flex-direction:column; 29 | justify-content:center; 30 | align-items: left; 31 | padding-left:12.5vw ; 32 | box-sizing: border-box; 33 | ` 34 | 35 | export const Title = styled.h1` 36 | color: #333; 37 | font-family: Roboto, Arial; 38 | font-size:40px; 39 | margin:12px; 40 | margin-left:0; 41 | ` 42 | export const Subtitle = styled.h2` 43 | color: #999; 44 | font-family: Roboto, Arial; 45 | font-size:16px; 46 | font-weight: 300; 47 | margin:8px; 48 | margin-left:0; 49 | margin-right:16px; 50 | 51 | a{ 52 | color:#7f56da; 53 | font-weight:bold; 54 | 55 | &:hover{ 56 | color:#613db7; 57 | cursor:pointer; 58 | } 59 | } 60 | ` 61 | 62 | export const FieldName = styled.h2` 63 | color: #777; 64 | font-family: Roboto, Arial; 65 | font-size:16px; 66 | font-weight: ; 67 | margin:8px; 68 | margin-left:0; 69 | ` 70 | 71 | export const InputField = styled.input` 72 | width: 25vw; 73 | height: 40px; 74 | border-radius: 8px; 75 | border: 1px solid #999; 76 | padding-left:8px; 77 | font-size: 16px; 78 | color: #777; 79 | box-sizing: border-box; 80 | 81 | 82 | &:focus{ 83 | border: 1px solid #999; 84 | outline:none; 85 | } 86 | 87 | &::placeholder{ 88 | color: #bbb; 89 | 90 | } 91 | 92 | ` 93 | 94 | export const SignIn = styled.button` 95 | width: 25vw; 96 | height: 40px; 97 | border-radius: 8px; 98 | background: #7f56da; 99 | color: white; 100 | font-size:16px; 101 | border: 0px; 102 | font-weight:400; 103 | 104 | margin: 16px 0px; 105 | 106 | &:hover{ 107 | background: #613db7; 108 | cursor:pointer; 109 | } 110 | 111 | ` 112 | 113 | export const Checkbox = styled.input.attrs({type:'checkbox'})` 114 | 115 | border: 1px solid #333; 116 | margin-right:8px; 117 | height: 16px; 118 | width: 16px; 119 | ` 120 | export const KeepSigned = styled.div` 121 | display: flex; 122 | justify-content:left; 123 | align-items:center; 124 | margin-top:16px 125 | ` -------------------------------------------------------------------------------- /src/Routes/Route.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from "react"; 2 | import { Routes, Route, Link, Navigate } from 'react-router-dom' 3 | import { ChildrenProps } from "../Contexts/deleteContext"; 4 | 5 | import AuthContext, {AuthType} from "../Contexts/authContext"; 6 | 7 | interface ProtectedRouteProps { 8 | children: React.ReactNode; 9 | priv:boolean; 10 | } 11 | 12 | const ProtectedRoute:React.FC = ({ children, priv}) => { 13 | 14 | const{userData} = useContext(AuthContext) as AuthType; 15 | 16 | 17 | 18 | 19 | if (!!userData.email === priv) { 20 | return <>{children}; 21 | }else{ 22 | return 25 | } 26 | 27 | 28 | }; 29 | 30 | export default ProtectedRoute; 31 | -------------------------------------------------------------------------------- /src/contextProviders.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { DeleteContextProvider } from "./Contexts/deleteContext"; 3 | import { TaskListContextProvider } from "./Contexts/taskListContext"; 4 | import { ChildrenProps } from "./Contexts/deleteContext"; 5 | import { CategoriesContextProvider } from "./Contexts/categoriesContext"; 6 | import { AddContextProvider } from "./Contexts/addContext"; 7 | import { AuthProvider } from "./Contexts/authContext"; 8 | 9 | const ContextProviders:React.FC=({children})=>{ 10 | return( 11 | 12 | 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | 20 | 21 | 22 | ) 23 | }; 24 | 25 | export default ContextProviders; -------------------------------------------------------------------------------- /src/global.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from "styled-components"; 2 | 3 | export default createGlobalStyle` 4 | *{ 5 | margin: 0; 6 | padding: 0; 7 | font-family: "Roboto", Arial; 8 | } 9 | 10 | html{ 11 | height:100vh; 12 | } 13 | 14 | body{ 15 | display: flex; 16 | flex-direction: row; 17 | height: 100vh; 18 | } 19 | `; -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | 5 | 6 | const root = ReactDOM.createRoot( 7 | document.getElementById('root') as HTMLElement 8 | ); 9 | root.render( 10 | 11 | 12 | 13 | ); 14 | 15 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | --------------------------------------------------------------------------------