├── .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 |
4 |
--------------------------------------------------------------------------------
/src/Img/arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/edit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/erase.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/filter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/folder.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/Img/folderFill.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/logout.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/Img/settings.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/Img/settingsFill.svg:
--------------------------------------------------------------------------------
1 |
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 |
--------------------------------------------------------------------------------