├── src ├── assets │ ├── plus.png │ ├── delete.png │ └── delete.svg ├── index.js ├── Components │ ├── NoteContainer │ │ ├── NoteContainer.css │ │ └── NoteContainer.js │ ├── Sidebar │ │ ├── Sidebar.css │ │ └── Sidebar.js │ └── Note │ │ ├── Note.css │ │ └── Note.js ├── index.css ├── App.css └── App.js ├── README.md ├── .gitignore ├── public └── index.html └── package.json /src/assets/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handyDev2/notes-app/HEAD/src/assets/plus.png -------------------------------------------------------------------------------- /src/assets/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handyDev2/notes-app/HEAD/src/assets/delete.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Notes App in React.js 2 | 3 | ![Screenshot (421)](https://user-images.githubusercontent.com/89729177/132137360-3515b331-6d30-48ea-9959-3b5815e66593.png) 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById("root") 11 | ); 12 | -------------------------------------------------------------------------------- /src/Components/NoteContainer/NoteContainer.css: -------------------------------------------------------------------------------- 1 | .note-container { 2 | height: 100%; 3 | } 4 | 5 | .note-container h2 { 6 | margin-bottom: 20px; 7 | } 8 | 9 | .note-container_notes { 10 | height: 90%; 11 | display: flex; 12 | flex-wrap: wrap; 13 | gap: 20px; 14 | overflow-y: scroll; 15 | } 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 10 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 11 | sans-serif; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Notes App 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | height: 100vh; 3 | display: flex; 4 | gap: 20px; 5 | padding: 40px; 6 | } 7 | 8 | .custom-scroll::-webkit-scrollbar { 9 | width: 8px; 10 | } 11 | .custom-scroll::-webkit-scrollbar-track { 12 | background-color: transparent; 13 | } 14 | 15 | .custom-scroll::-webkit-scrollbar-thumb { 16 | border-radius: 20px; 17 | background-color: lightgray; 18 | transition: 300ms; 19 | } 20 | 21 | .custom-scroll::-webkit-scrollbar-thumb:hover { 22 | background-color: gray; 23 | } 24 | -------------------------------------------------------------------------------- /src/Components/Sidebar/Sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | display: flex; 3 | flex-direction: column; 4 | gap: 40px; 5 | } 6 | 7 | .sidebar img { 8 | width: 60px; 9 | cursor: pointer; 10 | } 11 | 12 | .sidebar_list { 13 | display: flex; 14 | flex-direction: column; 15 | gap: 20px; 16 | align-items: center; 17 | height: 0; 18 | transition: 300ms; 19 | } 20 | 21 | .sidebar_list_active { 22 | height: 300px; 23 | } 24 | 25 | .sidebar_list_item { 26 | border-radius: 50%; 27 | height: 24px; 28 | width: 24px; 29 | list-style: none; 30 | } 31 | -------------------------------------------------------------------------------- /src/assets/delete.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Components/Note/Note.css: -------------------------------------------------------------------------------- 1 | .note { 2 | padding: 25px; 3 | height: 280px; 4 | width: 260px; 5 | display: flex; 6 | flex-direction: column; 7 | background-color: blueviolet; 8 | border-radius: 30px; 9 | } 10 | 11 | .note_text { 12 | flex: 1; 13 | resize: none; 14 | background-color: transparent; 15 | font-size: 1rem; 16 | line-height: 1.875rem; 17 | outline: none; 18 | border: none; 19 | } 20 | 21 | .note_footer { 22 | display: flex; 23 | justify-content: space-between; 24 | align-items: center; 25 | } 26 | 27 | .note_footer img { 28 | cursor: pointer; 29 | opacity: 0; 30 | transition: 300ms; 31 | } 32 | 33 | .note:hover .note_footer img { 34 | opacity: 1; 35 | } 36 | -------------------------------------------------------------------------------- /src/Components/Sidebar/Sidebar.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | 3 | import plusIcon from "../../assets/plus.png"; 4 | 5 | import "./Sidebar.css"; 6 | 7 | function Sidebar(props) { 8 | const colors = ["#fe9b72", "#fec971", " #00d4fe", "#b693fd", "#e4ee91"]; 9 | 10 | const [listOpen, setListOpen] = useState(false); 11 | 12 | return ( 13 |
14 | Add setListOpen(!listOpen)} /> 15 | 25 |
26 | ); 27 | } 28 | 29 | export default Sidebar; 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notes-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "react": "^17.0.2", 10 | "react-dom": "^17.0.2", 11 | "react-scripts": "4.0.3", 12 | "web-vitals": "^1.0.1" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Components/NoteContainer/NoteContainer.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Note from "../Note/Note"; 4 | 5 | import "./NoteContainer.css"; 6 | 7 | function NoteContainer(props) { 8 | const reverArray = (arr) => { 9 | const array = []; 10 | 11 | for (let i = arr.length - 1; i >= 0; --i) { 12 | array.push(arr[i]); 13 | } 14 | 15 | return array; 16 | }; 17 | 18 | const notes = reverArray(props.notes); 19 | 20 | return ( 21 |
22 |

Notes

23 |
24 | {notes?.length > 0 ? ( 25 | notes.map((item) => ( 26 | 32 | )) 33 | ) : ( 34 |

No Notes present

35 | )} 36 |
37 |
38 | ); 39 | } 40 | 41 | export default NoteContainer; 42 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import NoteContainer from "./Components/NoteContainer/NoteContainer"; 4 | import Sidebar from "./Components/Sidebar/Sidebar"; 5 | 6 | import "./App.css"; 7 | 8 | function App() { 9 | const [notes, setNotes] = useState( 10 | JSON.parse(localStorage.getItem("notes-app")) || [] 11 | ); 12 | 13 | const addNote = (color) => { 14 | const tempNotes = [...notes]; 15 | 16 | tempNotes.push({ 17 | id: Date.now() + "" + Math.floor(Math.random() * 78), 18 | text: "", 19 | time: Date.now(), 20 | color, 21 | }); 22 | setNotes(tempNotes); 23 | }; 24 | 25 | const deleteNote = (id) => { 26 | const tempNotes = [...notes]; 27 | 28 | const index = tempNotes.findIndex((item) => item.id === id); 29 | if (index < 0) return; 30 | 31 | tempNotes.splice(index, 1); 32 | setNotes(tempNotes); 33 | }; 34 | 35 | const updateText = (text, id) => { 36 | const tempNotes = [...notes]; 37 | 38 | const index = tempNotes.findIndex((item) => item.id === id); 39 | if (index < 0) return; 40 | 41 | tempNotes[index].text = text; 42 | setNotes(tempNotes); 43 | }; 44 | 45 | useEffect(() => { 46 | localStorage.setItem("notes-app", JSON.stringify(notes)); 47 | }, [notes]); 48 | 49 | return ( 50 |
51 | 52 | 57 |
58 | ); 59 | } 60 | 61 | export default App; 62 | -------------------------------------------------------------------------------- /src/Components/Note/Note.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import deleteIcon from "../../assets/delete.svg"; 4 | 5 | import "./Note.css"; 6 | 7 | let timer = 500, 8 | timeout; 9 | function Note(props) { 10 | const formatDate = (value) => { 11 | if (!value) return ""; 12 | 13 | const date = new Date(value); 14 | const monthNames = [ 15 | "Jan", 16 | "Feb", 17 | "March", 18 | "April", 19 | "May", 20 | "Jun", 21 | "Jul", 22 | "Aug", 23 | "Sept", 24 | "Oct", 25 | "Nov", 26 | "Dec", 27 | ]; 28 | 29 | let hrs = date.getHours(); 30 | let amPm = hrs >= 12 ? "PM" : "AM"; 31 | hrs = hrs ? hrs : "12"; 32 | hrs = hrs > 12 ? (hrs = 24 - hrs) : hrs; 33 | 34 | let min = date.getMinutes(); 35 | min = min < 10 ? "0" + min : min; 36 | 37 | let day = date.getDate(); 38 | const month = monthNames[date.getMonth()]; 39 | 40 | return `${hrs}:${min} ${amPm} ${day} ${month}`; 41 | }; 42 | 43 | const debounce = (func) => { 44 | clearTimeout(timeout); 45 | timeout = setTimeout(func, timer); 46 | }; 47 | 48 | const updateText = (text, id) => { 49 | debounce(() => props.updateText(text, id)); 50 | }; 51 | 52 | return ( 53 |
54 |